본문 바로가기

Java 길찾기/이것이 자바다

[Java] 예외 처리 코드

프로그램에서 예외가 발생했을 경우 프로그램의 갑작스러운 종료를 막고, 정상 실행을 유지할 수 있도록 처리하는 코드를 예외 처리 코드라고 한다. 자바 컴파일러는 소스 파일을 컴파일할 때 일반 예외가 발생할 가능성이 있는 코드를 발견하면 컴파일 오류를 발생시켜 개발자로 하여금 강제적으로 예외 처리 코드를 작성하도록 요구한다. 그러나 실행 예외는 컴파일러가 체크해주지 않기 때문에 예외 처리 코드를 개발자의 경험을 바탕으로 작성해야 한다. 예외 처리 코드는 try-catch-finally 블록을 이용한다. try-catch-finally 블록은 생성자 내부와 메소드 내부에서 작성되어 일반 예외와 실행 예외가 발생할 경우 예외 처리를 할 수 있도록 해준다. try-catch-finally 블록 작성 방법은 다음과 같다.

 

try-catch-finally문

 

try 블록에는 예외 발생 가능 코드가 위치한다. try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally 블록의 코드를 실행한다. 만약 try 블록의 코드에서 예외가 발생하면 즉시 실행을 멈추고 catch 블록으로 이동하여 예외 처리 코드를 실행한다. 그리고 finally 블록의 코드를 실행한다. finally 블록은 옵션으로 생략 가능하다. 예외 발생 여부와 상관없이 항상 실행할 내용이 있을 경우에만 finally 블록을 작성해주면 된다. try 블록과 catch 블록에서 return문을 사용하더라도 finally 블록은 항상 실행된다.

 

Class.forName() 메소드는 매개값으로 주어진 클래스가 존재하면 Class 객체를 리턴하지만, 존재하지 않으면 ClassNotFoundException 예외를 발생시킨다. ClassNotFoundException 예외는 일반 예외이므로 컴파일러는 개발자로 하여금 예외 처리 코드를 다음과 같이 작성하도록 요구한다.

// TryCatchFinallyExample.java
public class TryCatchFinallyExample {
    public statci void main(String[] args) {
        try {
            Class clazz = Class.forName("java.lang.String2");
        }
        catch(ClassNotFoundException e) {
            System.out.println("클래스가 존재하지 않습니다.");
        }
    }
}

 

위 예제를 실행시키면 4라인에서 ClassNotFoundException이 발생하는데, 이것은 java.lang.String2 클래스가 존재하지 않기 때문이다. 4라인에서 예외가 발생되면 5라인을 실행해서 예외 처리를 하게 된다. ArrayIndexOutOfException이나, NumberFormatException과 같은 실행 예외는 컴파일러가 예외 처리 코드를 체크하지 않기 때문에 오로지 개발자의 경험에 의해 예외처리를 다음과 같이 작성해주어야 한다.

// TryCatchFinallyRuntimeExceptionExample.java
public class TryCatchFinallyRuntimeExceptionExample {
    public static void main(String[] args) {
        String data1 = null;
        String data2 = null;
        try {
            data1 = args[0];
            data2 = args[1];
        }
        catch(ArrayIndexOutOfBoundsException e) {
            ...
        }
        
        try {
            int value1 = Integer.parseInt(data1);
            int value2 = Integer.parseInt(data2);
            int result = value1 + value2;
            System.out.println(data1 + "+" + data2 "=" + result);
        }
        catch(NumberFormatException e) {
            ...
        }
        finally {
            ...
        }
    }
}

 

 

예외 종류에 따른 처리 코드

다중 catch

try 블록 내부는 다양한 종류의 예외가 발생할 수 있다. 이 경우, 발생되는 예외별로 예외 처리 코드를 다르게 하려면 어떻게 하면 될까? 이것에 대한 해답은 다중 catch 블록을 작성하는 것이다. catch 블록의 예외 클래스 타입은 try 블록에서 발생된 예외의 종류를 말하는데, try 블록에서 해당 타입의 예외가 발생하면 catch 블록을 실행하도록 되어 있다.

 

다중 catch문

 

catch 블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다. 그 이유는 try 블록에서 동시다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동하기 때문이다.

 

catch 순서

다중 catch 블록을 작성할 때 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다. try 블록에서 예외가 발생했을 때, 예외를 처리해줄 catch 블록은 위에서부터 차례대로 검색된다. 만약 상위 예외 클래스의 catch 블록이 위에 있다면, 하위 예외 클래스의 catch 블록은 실행되지 않는다. 왜냐하면 하위 예외는 상위 예외를 상속했기 때문에 상위 예외 타입도 되기 때문이다. 따라서 다음은 잘못 코딩한 것이다.

 

잘못된 catch 블록 순서

 

ArrayIndexOutOfBoundsException과 NumberFormatExeption은 모두 Exception을 상속받기 때문에 첫 번째 catch 블록만 선택되어 실행된다. 두 번째 catch 블록은 어떤 경우에라도 실행되지 않는다. 위 코드는 다음과 같이 수정해야 한다.

 

정상 catch 블록 순서

 

멀티 catch

자바 7부터 하나의 catch 블록에서 여러 개의 예외를 처리할 수 있도록 멀티(multi) catch 기능을 추가했다. 다음은 멀티 catch 블록을 작성하는 방법을 보여준다.

 

멀티 catch 문

'Java 길찾기 > 이것이 자바다' 카테고리의 다른 글

[Java] 예외 떠넘기기  (0) 2022.02.16
[Java] 자동 리소스 닫기  (0) 2022.02.15
[Java] 예외  (0) 2022.02.11
[Java] 익명 객체  (0) 2022.02.10
[Java] 중첩 인터페이스  (0) 2022.02.09