개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › Java › 예외

예외와 finally

예외가 나면 어느 블록이 어떤 순서로 실행되나

try에서 예외가 나면 catch로 건너뛰고, finally는 try를 정상으로 빠져나가든 return이나 예외로 빠져나가든 실행됩니다. return이 끼어 있거나 catch 안에서 또 예외가 나면 순서가 헷갈리기 쉽습니다.

실행으로 대조 · JDK 21에서 32가지 조합을 실행해 대조

이 실습에 나오는 개념

finally와 try-with-resources
finally는 try 블록이 정상적으로 끝나든 예외가 발생하든 실행되는 블록으로(try 도중 System.exit() 등으로 JVM이 종료되는 경우는 예외다) 자원 정리에 쓴다. try-with-resources는 AutoCloseable을 구현한 자원을 try 괄호 안에 선언하면 블록이 끝날 때 자동으로 close()를 호출해 주는 구문으로, finally에서 직접 닫는 것보다 누락과 예외 처리 실수를 줄인다.
예외(Exception)와 Error
둘 다 프로그램 실행 중의 비정상 상황을 나타내는 Throwable의 하위 타입이다. Exception은 애플리케이션이 잡아서 처리할 수 있는 상황(잘못된 입력, 파일 없음 등)이고, Error는 메모리 부족이나 스택 오버플로처럼 JVM 수준의 심각한 문제라 애플리케이션이 복구를 시도하지 않는 것이 일반적이다.
Checked 예외와 Unchecked 예외
Unchecked 예외는 RuntimeException과 그 하위 클래스로(명세상으로는 Error 계열도 unchecked에 속한다), 컴파일러가 처리 여부를 검사하지 않는다(NullPointerException, IllegalArgumentException 등). Checked 예외는 그 밖의 Exception으로, 반드시 catch로 처리하거나 throws로 선언해야 컴파일된다(IOException, SQLException 등). 스프링의 @Transactional은 기본적으로 RuntimeException과 Error에서만 롤백하고 Checked 예외에서는 커밋한다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. "try 시작"을 출력한 뒤 IllegalArgumentException이 발생합니다. try 블록의 나머지 줄("try 끝")은 실행되지 않습니다.
  2. 예외 타입이 catch의 IllegalArgumentException과 맞습니다. catch 블록이 실행되고 예외는 처리된 것으로 봅니다.
  3. finally 블록이 실행됩니다.
  4. try-catch-finally가 끝나고 그다음 줄이 실행됩니다. "블록 다음"을 출력하고 2를 반환합니다.

실행 결과

코드

int run() {
    try {
        print("try 시작");
        if (fail) throw new IllegalArgumentException();  // fail은 true
        print("try 끝");
    } catch (IllegalArgumentException e) {
        print("catch");
    } finally {
        print("finally");
    }
    print("블록 다음");
    return 2;
}

이 모형의 전제

32가지 조합 모두에서 화면의 코드 그대로(값이 true인 fail 필드와 print, Resource만 더함)를 이 PC의 JDK 21에서 컴파일하고 실행해, 출력 순서와 최종 결과를 대조했습니다(verify/plain/exflow_code_check.js). 자원이 하나인 경우만 다뤘습니다. 자원이 여러 개면 연 순서의 반대로 닫히고, close()에서 난 예외는 원래 예외에 억제된 예외(suppressed)로 붙습니다.

앞 실습: Optional · 다음 실습: 체크 예외와 언체크 예외

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요