프로그램이 비정상적으로 동작하는 경우는 크게 오류(error)와 예외(Exception) 두가지가 있다.
오류는 시스템 레벨에서 프로그램에 심각한 문제를 야기하여 실행 중인 프로그램을 종료시킨다. 오류는 개발자가 미리 예측하여 처리할 수가 없는 것이 대부분이고, 오류에 대한 처리는 할 수가 없다.
예외는 프로그램을 비정상적으로 종료시키지만, 개발자가 미리 상황을 예측하여 처리할 수 있다.
try, catch, finally를 이용한다. 예외가 발생한 try에서 가장 가까운 catch 블록에서부터 해당 예외를 처리하는 catch 블록이 있는지 찾아보며, 찾지 못할 경우 가장 바깥쪽 catch 블록까지 찾아본다. 그래도 알맞은 catch 블록을 찾지 못하면 프로그램이 종료된다. 찾았을 경우 해당 catch 블록의 코드를 실행한 뒤 finally를 실행한다.
Exception클래스는 모든 예외의 조상 클래스로, 크게 RuntimeException 클래스, 그 외의 자식 클래스 두 가지로 분류된다.
RuntimeException 클래스와 그 자식 클래스들은 try, catch를 생략하더라도 컴파일 과정에서 에러가 나지 않는다. 그 외의 예외 클래스들은 자바 컴파일러가 예외 처리를 하도록 강제하기 때문에 try, catch를 사용해야 한다.
다음 예제의 경우 write 메서드를 try, catch로 감싸지 않으면 컴파일 시 오류가 발생한다.
public class Exception01 {
public static void main(String[] args) {
byte[] list = {'a', 'b', 'c'};
try {
System.out.write(list);
} catch (IOException e) {
e.printStackTrace();
}
}
}
다음 코드와 같이 Exception에 대한 예외 처리가 앞에 오면 IOException도 첫번째 catch 블록에서 처리될 것이다. IOException 클래스도 Exception의 자식 클래스이기 때문이다.
try {
System.out.write(list);
} catch (Exception e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
따라서 IOException을 따로 처리하려면 해당 catch 블록을 앞에 두어야 한다.
try {
System.out.write(list);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Java SE 7부터는 '|'(파이프) 기호를 이용하여 여러 예외를 동시 처리할 수 있다.
try {
this.db.commit();
} catch (IOException | SQLException e) {
e.printStackTrace();
}
클래스 | 설명 |
---|---|
ClassCastException | 수행할 수 없는 타입 변환이 진행될 경우 |
ArrayIndexOutOfBoundsException | 배열에 잘못된 인덱스를 사용하여 접근할 경우 |
NullPointerException | null 객체의 인스턴스 메소드를 호출하는 등의 경우 |
ArithmeticException | 산술 연산에서 정수를 0으로 나누는 등 연산을 수행할 수 없는 경우 |
Exception 클래스와 Error(모든 오류의 조상) 클래스의 부모 클래스로, Throwable이거나 자식 클래스이어야만 JVM이나 throw 키워드로 던져질 수 있다.
메서드 | 설명 |
---|---|
String getMessage() | 해당 throwable 객체에 대한 자세한 내용을 문자열로 반환함. |
void printStackTrace() | 해당 throwable 객체와 표준 오류 스트림(standard error stream)에서 해당 객체의 스택 트레이스(stack trace)를 출력함. |
String toString() | 해당 throwable 객체에 대한 간략한 내용을 문자열로 반환함. |
try {
System.out.println(5 / 0);
} catch (ArithmeticException e) {
System.out.println("현재 발생한 예외 정보 : " + e.getMessage());
}
다음의 경우 메서드에서 예외가 이미 처리되었기 때문에 main에서 처리되지 않는다.
public class Exception03 {
static void handlingException() {
try {
throw new Exception();
} catch (Exception e) {
System.out.println("호출된 메소드에서 예외가 처리됨!"); // 출력
}
}
public static void main(String[] args) {
try {
handlingException();
} catch (Exception e) {
System.out.println("main() 메소드에서 예외가 처리됨!");
}
}
}
메서드 선언부에 throws 키워드를 사용하여 해당 메서드 사용 시 예외를 미리 명시할 수 있다. 이렇게 하면 메서드 내에서는 try, catch 문을 사용하지 않아도 된다. 그리고 메서드 호출하는 곳에서는 그 예외에 대한 처리가 강제되어 안정성 있는 코드를 작성할 수 있다.
public class Exception04 {
static void handlingException() throws Exception {
throw new Exception();
}
public static void main(String[] args) {
try {
handlingException();
} catch (Exception e) {
System.out.println("main() 메소드에서 예외가 처리됨!"); // 출력
}
}
}
기존의 예외 클래스를 상속받은 자신만의 클래스를 만들 수 있다. 생성자 뿐만 아니라 필드 및 메서드로 원하는 만큼 추가할 수 있다.
class MyException extends RuntimeException {
MyException(String errMsg) {
super(errMsg);
}
}
예전의 경우 파일을 열거나 자원을 할당하는 명령문을 작성하면, 개발자가 따로 파일을 닫거나 자원 할당을 해제하는 코드를 작성해야 했다. 주로 finally를 이용한다.
static String readFile(String filePath) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(filePath));
try {
return br.readLine();
} finally {
if (br != null)
br.close();
}
}
그러나 Java SE 7부터 try 옆에 괄호 안에 파일을 열거나 자원을 할당하는 명령문을 작성하면, 해당 try 블록이 끝나면 자동으로 파일을 닫거나 할당된 자원을 해제해 준다.
static String readFile(String filePath) throws IOException {
try (BufferedReader br= new BufferedReader(new FileReader(filePath))){
return br.readLine();
}
}
Java에서는 각각의 스레드가 자신만의 호출 스택(call stack)을 가진다. 호출 스택은 프로그램을 실행하는 특정 지점에서 호출되어 있는 모든 메서드의 리스트를 말한다.
예외가 발생하면(Exception 객체가 생성되면) Throwable 클래스의 생성자가 Exception 객체의 stack trace를 call stack으로 채운다. 그 다음 예외가 throw되면 Java Runtime이 예외를 처리할 수 있는 메서드를 call stack에서 찾아본다.
call stack에서 예외를 처리할 수 있는 메서드가 없는 경우 Java 프로그램의 entry point에 해당하는 main 메서드가 stack trace를 출력하고 Java Runtime은 종료된다.
http://tcpschool.com/java/java_exception_intro
http://tcpschool.com/java/java_exception_class
http://tcpschool.com/java/java_exception_throw