자바에서 예외 처리를 처음 배우면 다음과 같은 코드를 자주 접하게 된다.
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
그런데 문득 이런 의문이 들었다.
catch 괄호 안에는 항상 Exception 클래스만 들어갈 수 있는 걸까? int나 String은 왜 사용할 수 없을까?
catch의 역할
try 블록 내부에서 예외가 발생하면 JVM은 해당 예외에 대한 객체를 생성한다.
예를 들어 아래 코드를 실행하면
int result = 10 / 0;
실제로는 ArithmeticException 객체가 생성된다.
개념적으로는 다음과 비슷하다.
ArithmeticException ex =
new ArithmeticException("/ by zero");
그리고 catch 문은 생성된 예외 객체를 전달받는다.
catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
여기서 e는 단순한 변수가 아니라 예외 객체를 참조하는 변수이다.
따라서 다음과 같은 메서드를 사용할 수 있다.
e.getMessage();
e.printStackTrace();
catch 안에 들어갈 수 있는 타입
catch 괄호 안에는 반드시 Throwable 클래스 또는 그 자식 클래스만 올 수 있다.
예를 들어 다음 코드는 모두 가능하다.
catch (ArithmeticException e) { }
catch (RuntimeException e) { }
catch (Exception e) { }
catch (Throwable e) { }
반면 아래 코드는 컴파일 오류가 발생한다.
catch (int a) { }
catch (String s) { }
catch (Object o) { }
왜냐하면 int, String, Object는 예외 타입이 아니기 때문이다.
Exception 계층 구조
자바의 예외는 상속 구조로 관리된다.
Throwable
├─ Error
└─ Exception
├─ RuntimeException
│ ├─ ArithmeticException
│ ├─ NullPointerException
│ └─ IllegalArgumentException
└─ IOException
따라서 ArithmeticException은 RuntimeException의 자식이고, RuntimeException은 Exception의 자식이다.
그래서 아래 코드는 ArithmeticException도 함께 처리할 수 있다.
catch (Exception e) {
System.out.println(e.getMessage());
}
여러 예외를 한 번에 처리하기
자바 7부터는 여러 예외를 하나의 catch 문에서 처리할 수 있다.
catch (ArithmeticException | IllegalArgumentException e) {
System.out.println(e.getMessage());
}
이는 다음 코드와 거의 동일한 의미를 가진다.
catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
중복 코드를 줄일 수 있다는 장점이 있다.
실무에서는 어떻게 사용할까?
실무에서는 모든 예외를 한 번에 처리하는 방식보다 구체적인 예외를 처리하는 방식을 선호한다.
catch (IOException e) { }
catch (SQLException e) { }
catch (UserNotFoundException e) { }
예외의 종류를 명확하게 구분할 수 있고, 상황에 맞는 처리가 가능하기 때문이다.
특히 Spring에서는 서비스 계층에서 예외를 발생시키고,
throw new UserNotFoundException();
전역 예외 처리기(GlobalExceptionHandler)가 이를 받아 처리하는 구조를 많이 사용한다.
마무리
catch 괄호 안에는 아무 타입이나 넣을 수 있는 것이 아니라 Throwable 또는 그 자식 클래스만 사용할 수 있다.
이는 catch 문이 단순히 값을 전달받는 것이 아니라, JVM이 생성한 예외 객체를 전달받아 처리하는 역할을 수행하기 때문이다.
즉,
catch (ArithmeticException e)
의 e는 단순한 변수가 아니라 실제 예외 객체이며, 자바의 예외 처리 메커니즘은 이러한 객체를 기반으로 동작한다.

'TIL' 카테고리의 다른 글
| [Troubleshooting] 자바 제네릭 T 타입으로 사칙연산이 불가능한 이유 (0) | 2026.06.08 |
|---|---|
| [TIL] 시간복잡도는 if문 개수보다 반복 횟수가 중요한 이유 (0) | 2026.06.06 |
| [TIL] 문자열에서 숫자를 추출하고 int로 변환하는 방법 (0) | 2026.06.02 |
| [TIL] 코딩테스트에서 Arrays 클래스가 중요한 이유 (0) | 2026.05.28 |
| [TIL] 코딩테스트를 풀다가 StringBuilder의 필요성을 직접 체감하다. (0) | 2026.05.27 |