자바 컴파일러는 소스 파일을 컴파일할 때 일반 예외가 발생할 가능성이 있는 코드를 발견하면 컴파일 에러를 발생시켜 개발자가 강제적으로 예외 처리 코드를 작성하도록 요구한다. 그러나 실행 예외는 컴파일러가 체크해주지 않기 때문에 개발자의 경험을 바탕으로 예외 처리 코드를 작성해야 한다.
예외 처리 코드
try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해준다. try-catch-finally 블록은 아래와 같이 작성한다.
try {
// 예외 발생 가능 코드 작성
} catch(예외클래스 e) {
// 예외 처리 코드
} finally {
// 항상 실행하는 코드
}
1. try 블록에는 예외 발생 가능 코드가 위치한다.
2. try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally블록의 코드를 실행한다. 만약 try 블록의 코드에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행한다. 그리고 finally 블록의 코드를 실행한다.
3. finally 블록은 생략이 가능하다. 예외 발생 여부와 상관없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성해주면 된다. 심지어 try 블록과 catch 블록에서 return문을 사용하더라도 fianlly 블록은 항상 실행한다.
예외 종류에 따른 처리 코드
예외의 총류에 따라 예외 처리 코드를 다르게 작성할 수 있다.
다중 catch
try 블록 내부는 다양한 예외가 발생할 수 있다. 이 경우 발생되는 예외별로 예외 처리 코드를 다르게 하려면 다중 catch 블록을 작성하면 된다. catch 블록의 예외 클래스 타입은 try 블록에서 발생된 예외의 종류를 말하는데, try 블록에서 해당 타입의 예외가 발생하면 catch 블록을 실행하도록 되어있다.
catch 블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다. 그 이유는 try 블록에서 동시 다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동하기 때문이다.
catch 순서
다중 catch 블록을 작성할 때 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다는 것이다. try 블록에서 예외가 발생했을 때, 예외를 처리해줄 catch 블록은 위에서부터 차례대로 검색된다. 만약 상위 예외 클래스의 catch 블록이 위에 있다면, 하위 예외 클래스의 catch 블록은 실행되지 않는다. 왜냐하면 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문이다.
따라서 아래의 코드는 잘못 작성한 예시이다.
try {
} catch(Exception e) {
} catch(ArrayIndexOutOfBoundsException e) {
}
ArrayIndexOutOfBoundsException, NumberFormatException.. 등 예외는 전부 Exception을 상속받기 때문에 어떤 오류가 발생하더라도 전부 첫 번째 catch 블록만 실행된다.
따라서 위 코드는 아래의 코드처럼 수정되어야 한다.
try {
} catch(ArrayIndexOutOfBoundsException e) {
} catch(Exception e) {
}
이 경우 try 에서 ArrayIndexOutOfBoundsException이 발생할 경우 첫 번째 catch 블록을 실행하고, 그 밖의 예외들이 발생하면 두 번째 catch 블록을 실행한다.
예외 떠넘기기
메소드 내부에서 예외가 발생할 수 있는 코드를 작성할 때 try-catch 블록으로 예외를 처리하는 것이 기본이지만, 경우에 따라서는 메소드를 호출한 곳으로 예외를 떠넘길 수도 있다. 이 때 사용하는 키워드가 throws이다. throws 키워드는 메소드 선언부 끝에 작성되어 메소드에서 처리하지 않은 예외를 호출한 곳으로 떠넘기는 역할을 한다. throws 키워드 뒤에는 떠넘길 예외 클래스를 쉼표로 구분해서 나열하면된다.
리턴 타입 메소드이름(매개변수, ...) thorws 예외클래스1, 예외클래스2, ... {
...
}
발생할 수 있는 예외의 종루별로 throws 뒤에 나열하는 것이 일반적이지만, 모든 예외들은 Exception을 상속하므로 throws Exception만으로 모든 예외를 간단히 떠넘길 수도 있다.
thorws 키워드가 붙어 있는 메소드는 반드시 try 블록 내에서 호출되어야 한다. 그리고 catch 블록에서 떠넘겨 받은 예외를 처리해야 한다. 아래 코드는 throws 키워드가 있는 method2() 를 method1() 에서 호출하는 방식이다.
public void method1() {
try {
method2();
} catch(ClassNotFoundException) { <-- 호출한 곳에서 예외 처리
// 예외 처리 코드
System.out.println("클래스가 존재하지 않습니다.");
}
}
public void method2() throws ClassNotFoundException {
Class class = Class.forName("java.lang.String2");
}
method1() 에서도 try-catch 블록으로 예외를 처리하지 않고 다음과 같이 throws 키워드로 다시 예외를 떠 넘길 수 있다. 그러면 method1() 을 호출하는 곳에서 try-catch 블록을 사용해서 예외를 처리해야 한다.
public void method1() throws ClassNotFountException {
method2();
}
자바 API 도큐먼트를 보면 클래스 생성자와 메소드 선언부에 throws 키워드가 붙어있는 것을 흔히 볼 수 있다. 이러한 생성자와 메소드를 사용하고 싶다면, 반드시 try-catch 블록으로 예외 처리를 해야한다. 아니면 throws를 다시 사용해서 예외를 호출한 곳으로 떠넘겨야 한다. 그렇지 않으면 컴파일 에러가 발생한다.
'Java' 카테고리의 다른 글
| 자바 java.util 패키지 (1) | 2023.06.28 |
|---|---|
| 자바 java.lang 패키지 (0) | 2023.06.28 |
| 자바 예외 클래스 (0) | 2023.06.28 |
| 자바 익명 객체 (0) | 2023.06.27 |
| 자바 중첩 클래스와 중첩 인터페이스 (0) | 2023.06.27 |