프로그램이 예기치 못하게 종료될 수 있는 오류는 에러와 예외로 나뉘고 예외는 프로그래머가 미리 처리할 수 있다고 앞 포스팅 글에서 정리했었다. 이 개념을 바탕으로 예외처리에 대한 정의는 다음과 같다.
예외처리 : 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것
- 예외처리의 목적은 예외의 발생으로 인한 실행 중인 프로그램의 비정상적인 종료를 막고 정상적인 실행 상태를 유지하게 하는 것임
발생한 예외를 처리하지 못하면 비정상적으로 프로그램이 종료되며 화면에 에러 종류가 출력되는데
Uncaught exception(처리 되지 않은 예외)를 JVM의 Uncaught exception handler(예외처리기)가 받아서 예외의 원인을 화면에 출력해주는 것이다.
예외는 Try-Catch를 통해 처리할 수있다.
Try 블록에는 예외가 발생할 수 있는 코드를 넣는다.
Catch에는 예외가 발생할 경우, 이를 처리하는 문장을 넣는다.
try {
// 예외가 발생할 가능성이 있는 문장들을 넣는다.
} catch (Exception1 e1) {
// Exception1 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception2 e2) {
// Exception2 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
} catch (Exception3 e3) {
// Exception3 이 발생했을 경우, 이를 처리하기 위한 문장을 적는다.
}
다음 코드에서 주목할 점은 에러가 발생하면 그 아래 코드는 실행되지 않는다는 것이다.
System.out.println(0 / 0); 부분에서 ArithmeticException 에러가 발생했을 시 아래
System.out.println(4)코드는 실행되지 않는 것을 볼 수 있다.
따라서 예외가 발생한 위치 이후에 있는 try블럭의 문장들은 수행되지 않기 때문에
try 블럭에 포함시킬 코드의 범위를 잘 선택해야한다.
class aaaa {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0 / 0); // 0으로 나눠서 고의로 ArithmeticException 에러 발생.
System.out.println(4); // 실행되지 않는다.
} catch (ArithmeticException ae) {
System.out.println(5);
} // try-catch의 끝
System.out.println(6);
}
}
출력값
1
2
3
5
6
다음 예시에서 첫번째 catch문에서 ArithmeticException 예외를 잡아주어 두번째 catch블럭은 검사하지 않게 된다.
만약 try 블럭 내에서 ArithmeticException 이 아닌 다른 종류의 예외가 발생한 경우에는
두번째 catch블럭인 Exception 클래스 타입의 참조변수를 선언한 곳에서 처리되었을 것이다.
이렇게 마지막에 Exception 타입으로 catch 해주면 어떤 종류의 예외가
발생하더라도 이 catch블록 의해 처리하게할 수 있다.
주의할 점은 맨 앞 catch 블록에 Exception클래스 타입으로 예외를 잡으면 세부 예외를 파악하기 어렵기 때문에 맨 앞 catch에 Exception클래스 사용은 자제하는 것이 좋다.
class aaaa {
public static void main(String args[]) {
System.out.println(1);
System.out.println(2);
try {
System.out.println(3);
System.out.println(0 / 0); // 0으로 나눠서 에러 발생.
System.out.println(4); // 실행되지 않는다.
} catch (ArithmeticException ae) {
if (ae instanceof ArithmeticException) {
System.out.println("true");
}
System.out.println("ArithmeticException");
} catch (Exception e) {
System.out.println("Exception");
} // try-catch의 끝
System.out.println(6);
} // main메서드의 끝
}
출력값.
1
2
3
true
ArithmeticException
6
예외가 발생하면 예외 객체가 생성된다.
예외객체 타입과 catch 블록에 참조변수 타입이 일치하면 예외 객체가 참조 변수에 할당된다.
예외 객체 내에는 예외에 관련된 정보가 들어있고, 객체의 예외 정보를 볼 수 있는 메소드는 여러개 있는데 그 중에서 대표적엔 메소드는 2개다.
아래 예시에서는 throw를 통해 예외를 발생시켰는데 다음 포스팅글에서 자세히 다루려고한다.
class Tes {
public static void main(String[] args) {
try {
Exception e = new Exception("고의로 발생시켰음.");
throw e; // 예외를 발생시킴
// throw new Exception("고의로 발생시켰음."); // 위 두 줄을 한 줄로 작성
} catch(Exception e) {
System.out.println("에러 메시지 : " + e.getMessage());
e.printStackTrace();
}
System.out.println("프로그램이 정상 종료되었음.");
}
}
참고 log4에서는 e.printStackTrace()를 log 안에 담을수 없기 떄문에
log.error("error : ", e); 로 사용하면 된다.
주니어녕- e.toString(), e.getMessage(), e.printStackTrace() 예외처리
mingseok-예외처리하기 - try-catch문, 코드참고
남궁성- 자바의 정석 P414~P430