이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
기초개념 › Java
예외는 무엇이고, try-catch는 무엇을 해 주는가
예외는 프로그램을 실행하는 중에 계속할 수 없는 일이 생겼을 때 자바가 던지는 객체입니다. 예를 들어 정수를 0으로 나누면 자바가 ArithmeticException이라는 예외를 던지고, 던지는 순간 하던 일을 그 자리에서 멈춥니다. 아무도 잡지 않으면 프로그램은 거기서 끝나고 그 뒤의 줄은 실행되지 않습니다. try { }는 문제가 날 수 있는 코드를 감싸는 것이고, 뒤에 붙인 catch (예외의 종류 e) { }는 그 종류의 예외가 났을 때 실행이 건너와 처리하는 곳입니다. 처리가 끝나면 try-catch 아래의 줄을 계속 실행합니다. 이 실습은 try-catch를 지우고, b의 값을 바꾸고, catch가 잡는 종류를 바꿔 가며 같은 코드를 컴파일하고 실행해, 무엇이 출력되고 프로그램이 어떻게 끝나는지를 봅니다.
실행으로 대조 · JDK 21에서 여덟 가지 조합을 javax.tools로 컴파일하고 자식 java 프로세스로 실행해, 표준 출력·표준 오류·종료 코드를 대조
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 0;
// try: 문제가 날 수 있는 코드를 감싼다
try {
System.out.println(a / b);
// catch: 예외가 나면 여기로 건너온다
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없습니다");
}
System.out.println("끝");
}
}
컴파일러와 실행 환경은 JDK 21.0.12.1(javac 21)입니다. 여덟 가지 조합을 모두, 화면의 코드와 같은 소스(줄 단위로 같은 글)를 javax.tools로 컴파일해 모두 컴파일되는 것을 확인했고, 컴파일된 Main을 이 JDK의 java를 자식 프로세스로 띄워 실제로 실행해 표준 출력, 표준 오류, 종료 코드를 잡은 결과와 대조했습니다. 대조한 것은 컴파일 성공 여부, 표준 출력의 줄들(결과 표의 출력 열), 종료 코드와 표준 오류의 첫 줄(프로그램이 끝난 방식 열: 정상이면 종료 코드 0에 표준 오류가 비어 있었고, 멈추면 종료 코드 1에 첫 줄이 Exception in thread "main" java.lang.ArithmeticException: / by zero였으며 표준 오류에 Main.main이 있는 스택 추적이 이어졌습니다), catch 안의 코드가 실행됐는지(catch 안의 println이 출력한 글이 표준 출력에 있는지)입니다. 멈춘 조합은 모두 표준 출력이 비어 있어 "끝"이 출력되지 않았습니다. try-catch가 없는 조합은 catch가 잡는 종류 설정이 쓰이지 않아 두 조합의 결과가 같습니다. 문서는 Java Language Specification(Java SE 21)을 직접 열어 확인했습니다. 규칙을 어기면 자바 가상 머신이 예외로 알리고 프로그램이 정한 곳으로 제어가 옮겨진다는 것은 11장 서두, 예외가 던져지면 가장 가까이 둘러싼 try의 그 예외를 처리할 수 있는 catch로 제어가 옮겨지고 예외를 일으킨 코드는 다시 실행되지 않으며 처리할 catch가 없으면 그 스레드가 끝난다는 것은 11.3절, throw가 즉시 제어를 옮기고 맞는 try가 없으면 그 스레드가 끝난다는 것은 14.18절, catch의 매개변수는 하나이고 그 종류는 Throwable이거나 그 하위 클래스여야 한다는 것은 14.20절, 던져진 값의 종류가 catch에 적은 종류에 대입할 수 있으면 가장 왼쪽의 맞는 catch가 선택되어 그 블록이 실행되고 그 블록이 정상으로 끝나면 try 문도 정상으로 끝나며 맞는 catch가 없으면 try 문이 같은 예외로 끝난다는 것은 14.20.1절, 정수 나눗셈에서 나누는 수가 0이면 ArithmeticException이 던져진다는 것은 15.17.2절을 따랐습니다. 14.20.1절의 맞는 종류에는 적은 종류의 하위 종류도 들어가지만, 이 실습의 catch는 ArithmeticException과 NullPointerException뿐이고 둘은 서로 상하 관계가 아니어서 하위 종류를 잡는 경우는 다루지 않았습니다. 표준 오류에 나온 글과 종료 코드 1은 명세가 정한 것이 아니라 이 java에서 관찰한 것입니다. 화면의 코드는 java Main으로 실행하는 모양 그대로이고 패키지는 없습니다. 그림의 10 / 0과 10 / 2는 a와 b에 담은 값을 풀어 쓴 것입니다. 예외에는 이 밖에도 catch를 여러 개 쓰는 것, finally, throw로 직접 던지기, 호출한 메서드를 거슬러 올라가며 잡는 곳을 찾는 것, 체크 예외가 있지만 이 실습은 다루지 않았습니다. 이것들은 "세부 동작 실습: 예외와 finally"에서 다룹니다.
줄을 그은 곳은 처음 코드에서 지운 것이고, 색을 칠한 곳은 새로 쓴 것입니다.