네, Java에서는 메소드 내에 return 문이 있더라도 finally 블록은 반드시 실행됩니다.
finally 블록은 try-catch 구문에서 예외가 발생하든 발생하지 않든 항상 실행됩니다. 심지어 try 블록이나 catch 블록에서 return 문을 만나 메소드가 종료되려는 시점에도, 실제로 값을 반환하기 전에 finally 블록이 먼저 실행됩니다.
다만 finally 블록이 실행되지 않는 몇 가지 예외적인 상황이 존재합니다.
- finally 블록 안에서 명시적으로 System.exit() 메소드를 호출하는 경우
- JVM 크래시(JVM 비정상 종료)가 발생한 경우
- 정전이나 운영체제 수준의 소프트웨어 비정상 종료가 발생한 경우
이러한 특수한 상황을 제외하면, finally 블록은 어떤 경우에도 항상 실행된다고 보면 됩니다. 따라서 파일 스트림 닫기, 데이터베이스 연결 해제, 락(lock) 해제 등 리소스 정리 작업은 finally 블록에 작성하는 것이 안전합니다.
예제 코드
public class FinallyBlockAfterReturnTest {
public static void main(String[] args) {
System.out.println(count());
}
public static int count() {
try {
return 1;
} catch(Exception e) {
return 2;
} finally {
System.out.println("return 문 이후에도 finally 블록이 실행됩니다");
}
}
}
위 예제에서 count() 메소드는 try 블록에서 return 1;을 만나 즉시 종료될 것처럼 보이지만, 실제 실행 순서는 다음과 같습니다.
- try 블록에서
return 1;을 만나 반환값 1이 임시로 저장됩니다. - 메소드가 실제로 종료되기 전에 finally 블록이 실행됩니다.
- finally 블록의 실행이 끝난 후 저장된 값 1이 호출자에게 반환됩니다.
실행 결과
return 문 이후에도 finally 블록이 실행됩니다 1
실행 결과에서 확인할 수 있듯이, return 문이 실행된 후에도 finally 블록의 출력문이 먼저 콘솔에 표시되고, 그다음 반환값 1이 출력됩니다. 이처럼 finally 블록은 메소드의 반환 흐름보다 우선하여 실행되므로, 예외 처리와 무관하게 반드시 수행해야 하는 로직을 배치하기에 적합합니다.