자바에서는 실행 시 발생할 수 있는 오류를 크게 두 가지로 분류합니다.
자바의 모든 예외와 에러는 Throwable 클래스를 상속받습니다. 여기서 예외(Exception)는 다시 두 갈래로 나뉩니다.
| 구분 | Checked Exception | Unchecked Exception (Runtime) |
|---|---|---|
| 대표 클래스 | IOException, SQLException | RuntimeException 하위 클래스들 |
| 체크 시점 | 컴파일 단계에서 확인 | 실행 시점(Runtime)에 발생 |
| 처리 강제 | 반드시 try-catch나 throws 필요 | 명시적인 처리를 강제하지 않음 |
| 의미 | 외부 환경(파일, 네트워크)에 의한 오류 | 개발자의 실수(0으로 나누기, 인덱스 초과) |
💡 비유로 이해하기
- Unchecked: 길을 걷다 돌부리에 걸리는 것. 조심하면 예방할 수 있기에 미리 구급차를 대기시키지 않습니다.
- Checked: 태풍이 오는 날 외출하는 것. 아무리 조심해도 사고가 날 수 있으니, 국가(컴파일러)가 우비나 장화(
try-catch)를 챙기지 않으면 밖으로 나가지 못하게 막는 것과 같습니다.
try {
// (1) 예외 발생 가능성이 있는 코드
// (2) 정상 실행 시 다음 코드
} catch (ArithmeticException e) {
// (3) 특정 예외 발생 시 처리할 코드
} finally {
// (4) 예외 발생 여부와 상관없이 '무조건' 실행
}
finally 블록은 try나 catch 안에 return 문이 있더라도 반드시 실행된 후 메서드가 종료됩니다.하나의 try 블록에서 여러 종류의 예외가 발생할 수 있습니다. 이때 catch 문을 작성하는 중요한 규칙이 있습니다.
"좁은 범위(자식)에서 넓은 범위(조상) 순으로 작성하라!"
예외 객체가 발생하면 위에서부터 차례대로 instanceof로 체크하며 내려옵니다. 만약 가장 상위 클래스인 Exception을 첫 번째 catch에 두면, 아래에 있는 상세한 예외 블록들은 절대 실행될 기회를 얻지 못합니다.
파일이나 네트워크 연결 같은 자원(Resource)은 사용 후 반드시 close()를 호출해야 합니다. 예전에는 finally 블록 안에서 또 try-catch를 써가며 지저분하게 코드를 짰지만, JDK 7부터는 아주 깔끔해졌습니다.
// AutoCloseable 인터페이스를 구현한 객체만 가능
try (FileInputStream fis = new FileInputStream("data.txt")) {
// 로직 수행
} catch (IOException e) {
e.printStackTrace();
} // 블록을 벗어나는 순간 fis.close()가 자동 호출됨
throw new MyException("에러 발생");)부모 클래스의 메서드를 자식 클래스에서 재정의할 때, 던질 수 있는 예외에도 규칙이 있습니다.
RuntimeException 계열은 부모 메서드에 상관없이 자유롭게 던질 수 있습니다.class Parent {
void service() throws IOException {}
}
class Child extends Parent {
@Override
// void service() throws Exception { } // (X) 부모보다 큰 예외 불가
void service() throws FileNotFoundException { } // (O) 더 구체적인 예외 가능
}
도메인 특화된 에러를 표현하고 싶을 때 직접 예외 클래스를 만듭니다.
// 1. 클래스 생성 (Exception 혹은 RuntimeException 상속)
public class ItemNotFoundException extends RuntimeException {
public ItemNotFoundException(String itemName) {
super(itemName + "을(를) 찾을 수 없습니다.");
}
}
// 2. 활용 예제
public void findItem(String name) {
if (!store.contains(name)) {
throw new ItemNotFoundException(name); // 명시적 발생
}
}
try-with-resources를 사용하기 위해 구현해야 하는 인터페이스는?AutoCloseableChecked Exception은 어떤 상황에서 주로 쓰이나요?