SecurityManager의checkExit()메소드를 오버라이드하여 종료 코드에 따른 예외처리가 가능하다.
예제 코드
public class Main {
public static void main(String[] args) {
SecurityManager securityManager = new SecurityManager() {
@Override
public void checkExit(int status) {
System.out.println("status = " + status);
if(status == 0) {
System.out.println("정상적으로 종료되었습니다.");
} else {
System.out.println("비정상적으로 종료되었습니다.");
throw new SecurityException("예외처리를 해주세요.");
}
}
};
System.setSecurityManager(securityManager);
// usualExit();
unusualExit();
}
public static void usualExit() {
System.out.println("정상적으로 프로그램을 종료시킵니다.");
System.exit(0); // 0: 정상
}
public static void unusualExit() {
System.out.println("비정상적으로 프로그램을 종료시킵니다.");
System.exit(1); // 1: 비정상
}
}
예제 코드를 실행시키면 위와 같은 결과가 나타난다.
가비지 콜렉터 실행(gc())
일반적으로 가비지 콜렉터는 CPU가 한가하거나 메모리가 부족할 때 JVM에서 자동으로 실행한다.
System.gc()를 실행하면 가비지 콜렉터 수행 시점을 조금 앞당길 수 있다.
바로 실행되는 것은 아니고 빠른 시간 내에 실행시키기 위해 노력하는 것이다.
수집되는 순간 이전에 배웠던.finalize()메소드가 실행된다.
현재시각 읽기(currentTimeMillis(), nanoTime())
currentTimeMillis(): 현재 시간을 밀리 세컨드(1/1000초) 단위로 출력
nanoTime(): 현재 시간을 나노 세컨드(1/10^9초) 단위로 출력
프로그램 실행 소요시간 측정에 사용된다.
반환 타입은long이다.
시스템 프로퍼티 읽기(getProperty())
JVM이 시작할 때 자동으로 갖게 되는 시스템의 속성 값을 반환한다.
java.version: 자바 버전
java.home: JRE의 설치 경로
os.name: 운영체제 이름
file.separator: 파일 구분자 (윈도우는\)
user.name: 사용자 이름
user.home: 사용자의 홈디렉토리
user.dir: 사용자가 현재 작업중인 디렉토리 경로
System.getProperties()메소드를 이용해 프로퍼티 정보를 받으면 위에 나열된 값 이외에도 많은 프로퍼티를 한번에 볼 수 있다.
환경 변수 읽기(getEnv())
운영체제에 설정된 환경변수를 가져올 수 있다.
System.getenv()메소드를 이용하면 모든 환경변수가 들어있는Map형태의 값이 반환된다.
Class 클래스
클래스, 인터페이스의 메타데이터를 얻을 수 있다.
클래스의 메타데이터란 클래스의 이름, 생성자 정보, 필드 정보, 메소드 정보 등을 말한다.
Class 객체를 얻는 방법
object.getClass()메소드를 수행하여 얻을 수 있다.
Class.forName()메소드를 수행하여 얻을 수 있다.
해당 클래스가 존재하지 않는 경우의 예외처리를 위해ClassNotFoundException을 처리해주어야 한다.
리플렉션
Class객체를 이용해 메타데이터를 알아낼 때 이용된다.
클래스 이름
생성자 정보
필드 정보
메소드 정보
Class객체에서 리플렉션을 얻는 방법
.getDeclaredConstructors():Constructor객체의 배열을 반환
.getDeclaredFields():Field객체의 배열을 반환
.getDeclaredMethods():Method객체의 배열을 반환
예제 코드
public class Myself {
String name = "Jake Seo";
int birthYear = 1992;
int koreanAge;
String[] favoriteFoods = {"김치", "밥"};
public Myself() {
koreanAge = LocalDateTime.now().getYear() - birthYear + 1;
}
public Myself(int thatYear) {
koreanAge = thatYear - birthYear + 1;
}
public String getName() {
return name;
}
public int getKoreanAge() {
return koreanAge;
}
public String[] getFavoriteFoods() {
return favoriteFoods;
}
}
public class Main {
public static void main(String[] args) {
Class myselfClass = Myself.class;
Field[] declaredFields = myselfClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("declaredField = " + declaredField);
}
Constructor[] declaredConstructors = myselfClass.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("declaredConstructor = " + declaredConstructor);
}
Method[] declaredMethods = myselfClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("declaredMethod = " + declaredMethod);
}
}
}
동적 객체 생성(newInstance())
new연산자를 사용하지 않고 객체를 생성하는 방법이다.
클래스의 이름이 런타임 시에 결정되는 경우에 사용된다.
기본 생성자를 호출해서 객체를 생성하기 때문에, 반드시 기본 생성자가 있어야 한다.
매개변수가 있는 생성자를 호출하고 싶다면 리플렉션을 이용해서Constructor객체를 얻어야 한다.
추상 클래스나 인터페이스를 이용해 인스턴스를 만드려하면InstantiationException예외가 발생한다.
클래스나 생성자가 접근 제한자로 인해 접근할 수 없다면IllegalAccessException예외가 발생한다.
메소드의 반환 타입이Object라서 강제 형변환을 해야 하는데, 보통 인터페이스를 이용한 다형성으로 처리한다.
String 클래스
java.lang패키지에 속해있다.
문자열 리터럴은 자동으로String객체로 생성된다.
Deprecated된 생성자 외에도 13개의 생성자를 더 제공한다.
파일의 내용을 읽거나, 네트워크를 통해 받은 데이터는 보통byte[]이므로 이것을 문자열로 변환하기 위해 사용한다.
// 특정 인코딩으로 넘어온 바이트 배열을 문자열로 변경하는 생성자
String str = new String(byte[] bytes, String charsetName);
키보드에서 문자열을 입력받아 출력하는 생성자 예제 코드
public class Main {
public static void main(String[] args) {
byte[] bytes = new byte[100];
try {
System.out.print("문자열 입력: ");
int readByteLength = System.in.read(bytes);
System.out.println("\n읽어들인 문자의 수 = " + readByteLength);
System.out.println("입력된 내용 = " + new String(bytes, 0, readByteLength - 1));
} catch (IOException e) {
e.printStackTrace();
}
}
}
.charAt() 메소드
char/ 특정 위치의 문자를 반환한다.
.equals() 메소드
boolean/ 두 문자열을 비교한다.
.getBytes() 메소드
byte[]/ 문자열을 바이트 배열로 반환한다.
인자로UTF-8같은 캐릭터셋 유형을 주면, 해당 캐릭터셋에 맞게 반환해준다.
네트워크로 문자열을 전송하거나, 문자열을 암호화할 때 유용하다.
EUC-KR문자셋을 이용하여 인코딩하면 영어 1바이트 한글 2바이트가 된다. UTF-8문자셋을 이용하여 인코딩하면 영어 1바이트 한글 3바이트가 된다. 기본 값은 시스템의 기본 문자셋을 이용한다. 존재하지 않는 문자셋을 입력하면java.io.UnsupportedEncodingException예외가 발생한다.
.indexOf() 메소드
문자열 내에서 주어진 문자열의 위치를 인덱스 기준의 숫자로 반환한다.
없으면 -1 반환
.length() 메소드
총 문자열의 길이를 반환한다.
.replace() 메소드
인자로target과replacement를 받아서target이replacement로 대체된 결과 문자열을 반환한다.
.substring()
지정된 위치에서 끝까지 잘라낸 새로운 문자열을 반환한다.
인자를 2개 주면 두번째 인자까지 잘라낸 새로운 문자열을 반환한다.
toLowerCase(), toUpperCase()
대문자 혹은 소문자로 변환한다.
대소문자 문자 비교 때는.equalsIgnoreCase()메소드를 이용하면 대소문자 무시 비교를 할 수 있다.
trim()
앞뒤 공백을 제거한 문자를 반환한다.
valueOf()
기본 타입값을 문자열로 반환한다.
StringTokenizer 클래스
주로 문자열이 특정한 구분자(delimiter)로 연결된 구조일 때, 특정한 구분자를 기준으로 문자열을 분리할 때 사용된다.
String클래스에도.split()메소드가 있어서 특정 구분자를 기준으로 문자열을 나눌 수 있지만, 정규표현식을 이용해야 한다.StringTokenizer클래스가 제공하는.split()은 단순히 문자delimeter만 구분해서 나누는 방식이다.
String.split()
public class StringTokenizerTest {
String exampleString = "김철수,이미영-김문수";
@Test
public void stringSplitTest() {
String[] split = exampleString.split(",|-");
for (String s : split) {
System.out.println("s = " + s);
}
}
}
위와 같이 정규표현식을 이용하여 구분할 수 있다. 예제 문자열은 이름이,혹은-로 구분되어 있는데, 두 문자를 모두 구분자로 이용하기 위한 정규표현식이",|-"라는 문자열로 표현되었다.
StringTokenizer 생성자
문자열이 한 종류의 구분자로 되어있을 때 용이하며, 말 그대로 문자열을 토큰화한다. 토큰화한 문자열을 다루기 위해 3가지 내장 메소드를 제공한다.
int countTokens(): 꺼내지 않고 남아있는 토큰의 수를 반환한다.
boolean hasMoreTokens(): 남아 있는 토큰이 있는지 여부에 대해 반환한다.
댓글