C++에서 배우는 자바-예외 처리

예외 처리

java에선 에러를 3가지 종류로 정의한다.

  • 컴파일 에러 : 컴파일 시에 발생하는 에러
  • 런타임 에러 : 프로그램 실행 시에 발생하는 에러
  • 논리적 에러 : 실행은 되지만, 원하는 결과가 나오지 않는 에러

이 중에서 런타임 에러는 또 2가지로 나뉜다. 메모리 부족(OutOfMemoryError)이나 스택 오버플로우(StackOverflowError)와 같은 복구가 불가능한 심각한 오류를 에러(error), 이외에 발생하더라도 수습할 수 있는 것을 예외(exception)라 한다.
자바에선 예외가 Exception 클래스부터 시작해서 많은 자식 클래스들로 세분화되어 있고, 이를 이용하여 예외 처리가 가능하다.

try-catch

예외처리의 기본은 try-catch 문이다. 예외에 대비한 코드를 미리 짜놓음으로써 프로그램의 비정상적인 종료를 막고 정상적인 실행을 보장하는 것이다. 형식은 다음과 같다.

try {
    //예외가 발생할 수 있는 구문들
} catch(Exception1 e1) {
    //Exception1이 발생했을 경우 대비할 구문
} catch(Exception2 e2) {
    //Exception2가 발생했을 경우 대비할 구문
}....

만약 try블럭 내부에서 예외가 발생했다면, 예외와 일치하는 catch 구문이 있는지 확인한 뒤 catch 블럭을 실행한 후 전체 try-catch 문을 빠져나간다. 만약 일치하는 catch문이 없다면 예외는 처리되지 않는다.
예외가 발생하지 않을 경우 전체 try-catch문을 빠져나간다.

예외가 발생했을 때, catch 블럭 내에서 printStackTrace() 메서드와 getMessage() 메서드를 이용하여 예외에 대한 정보를 얻을 수 있다. 예를 들어

public static void main(String args[]) {
    try {
        int i=0/0;
    } catch(ArithmeticException ae) {
        ae.printStackTrace();
        System.out.println(ae.getMessage);
    }
}

위와 같이 코드를 작성할 경우, 일부로 0을 0으로 나눠 ArithmeticException 예외를 일부러 발생시킨 후 printStackTrace() 메서드로 예외발생 당시 스택에 있던 메서드의 정보와 예외 메시지를 얻을 수 있고, getMessage() 메서드를 통해 예외 메시지를 출력하므로 어느 메서드에서 예외가 발생했는지, 왜 발생했는지를 알 수 있다.

throw

throw 구문을 통해 고의로 예외를 발생시킬 수 있다. 예를 들어

public static void main(String args[]) {
    try {
        Exception e=new Exception("고의발생");  
        throw e;
    } catch(Exception e) {
        System.out.println(e.getMessage);
    }
}

위와 같이 예외를 생성할 때 String 구문을 넣으면 예외 메세지를 임의로 지정할 수 있다. 생성된 예외를 throw를 통해 발생시키고, catch 구문에서 받아 “고의발생”이라는 메세지를 출력하게 된다.

finally

만약 예외가 처리되도, 예외가 발생하지 않아도 이후에 꼭 실행되어야 하는 구문이 있다면, finally 블럭을 사용할 수 있다. catch 블럭 이후에 finally 블럭을 붙여주기만 하면 되는데 예를 들어

public static void main(String args[]) {
    try {
        Exception e=new Exception("고의발생");  
        throw e;
        return;
    } catch(Exception e) {
        System.out.println(e.getMessage);
    } finally {
        System.out.println("finally 블럭 실행");
    }
}

finally 블럭의 장점은 무조건 실행된다는 것이다. 위의 코드와 같이 try문 내부에서 return문으로 메서드가 종료되더라도 finally 구문은 실행되어 “finally 블럭 실행”이라는 메세지를 출력한다.

이외에도 부모 예외의 참조변수를 이용하여 여러 예외를 처리하는 것 또한 가능하다. 상속을 통해 부모 클래스의 참조변수를 이용하는 것과 비슷하다.