예외처리(Exception Handling) : 프로그램 실행 시 발생할 수 있는 예기치 못한 예외의 발생에 대비한 코드를 작성하는 것
목적 : 예외의 발생으로 인한 실행 중인 프로그램의 갑작스러운 비정상 종료를 막고, 정상적인 실행상태를 유지할 수 있도록 하는 것
프로그램 오류 : 프로그램 실행 중 오작동 하거나 비정상적으로 종료되는 경우의 원인
| 에러 종류 | 발생 시점 | 원인 | 예시 |
|---|---|---|---|
| 컴파일 에러 (Compile-time Error) | 코드 작성 후 컴파일 시 | 문법 오류, 타입 불일치, 선언되지 않은 변수 사용 등 | - 세미콜론(;) 누락 - 존재하지 않는 클래스나 메서드 호출 - 잘못된 타입 변환 ( int를 String에 할당) |
| 런타임 에러 (Runtime Error) | 프로그램 실행 중 | 실행 중 예외 발생, 메모리 부족, 잘못된 연산 | - NullPointerException (null 객체 접근) - ArrayIndexOutOfBoundsException (배열 범위 초과) - ArithmeticException (0으로 나누기) |
| 논리적 에러 (Logical Error) | 실행은 되지만 의도한 결과가 나오지 않음 | 알고리즘 오류, 잘못된 조건문 사용 | - if (a = b) {} (비교 연산자 == 대신 = 사용) - 반복문 조건 오류로 무한 루프 발생 - 올바른 값이 출력되지 않음 |
에러(error) : 코드로 처리할 수 없는 심각한 오류
예외(exception) : 코드로 처리할 수 있는 다소 미약한 오류
* Exception 클래스의 RuntimeException을 제외한 예외는 Checked 예외이다
Checked Exception : 컴파일 타임 예외. 사용자의 실수와 같은 외적 요인에 의해 발생한다 (반드시 예외처리를 해야한다)
Unchecked Exception : 런타임 예외. 프로그래머의 실수로 발생한다
try-catch 문을 사용해서 예외를 처리할 수 있다
try {
// 예외가 발생할 가능성이 있는 문장들
} catch (Exception e) {
// Exception이 발생했을 경우 처리할 문장들
} finally {
// 예외 발생여부와 관계없이 수행되어야하는 문장들
}
사용한 자원을 반드시 반환해야 하는 경우, try-with-resources문으로 처리할 수 있다
괄호안에 객체를 생성하는 문장을 넣으면 try 블럭을 벗어나는 순간 close()가 자동으로 호출된다
try (FileInputStream fls = new FileInputStream("score.dat"); DataInputStream dis = new DataInputStream(fls)) {
// 예외가 발생할 가능성이 있는 문장들
} catch (Exception e) {
// Exception이 발생했을 경우 처리할 문장들
}
자원을 사용하고 반환해야 하는 경우 두 가지 경우를 생각해볼 수 있다
1. close() 에서 예외가 발생하는 경우
2. close() 와 try 블럭 내에서 모두 예외가 발생하는 경우
try-catch 문을 사용할 경우finally 블럭에서 예외 처리 → 가능하지만 코드가 복잡해진다try 블럭의 예외는 무시된다try-with-resources 문을 사용할 경우close() 에 대한 예외가 발생try 블럭 내에서 발생한 예외 내부에 close()에 대한 예외가 저장된다 → suppressed 로 저장된다Throwable의 suppressed exception 관련 메서드
void addSuppressed(Throwable exception)Throwable[] getSuppressed()Throwable에 구현된 printStackTrace()와 getMessage()를 사용해서 예외에 대한 정보를 출력하거나 얻을 수 있다
printStackTrace() : 예외발생 당시 Call Stack에 있었던 메서드의 정보와 예외 메세지를 화면에 출력getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메세지 반환throw 키워드를 사용해서 고의로 예외를 발생시킬 수 있다
예외 클래스의 객체를 생성한 다음 throw 객체명; 으로 사용한다
해당 메서드에서 발생 가능성이 있는 예외들을 선언할 수 있다
선언한 예외가 발생할 가능성이 있으니 호출한 곳에서 처리하라는 뜻이다
void method() throws Exception1, Exception2, ... {
...
}
Exception class 나 RuntimeException class 로부터 상속받아 예외 클래스를 만들 수 있다 (필요에 따라 다른 예외클래스를 상속받아도 된다)
가능하면 기존의 예외클래스를 활용하는 것이 좋다
class MyException extends Exception {
MyException(String msg) {
super(msg);
}
}
catch 블럭에서 throw를 통해 예외를 되던질 수 있다
하나의 예외에 대해 예외가 발생한 메서드와 호출한 메서드 양쪽 모두 처리해야 할 작업이 있을 때 사용한다
연결된 예외(chained exception) : 한 예외가 발생했을 때, 그 예외의 원인이 되는 또 다른 예외를 포함하여 처리하는 기법
Throwable의 suppressed exception 관련 메서드
Throwable initCause(Throwable cause) : 원인 예외로 등록Throwable getCause() : 원인 예외 반환연결된 예외를 사용하는 경우