3 minute read

목표

자바의 예외 처리에 대해 학습하세요.

학습할 것 (필수)

자바에서 예외 처리 방법 (try, catch, throw, throws, finally)

예외: 프로그램 실행 중에 발생하는 에러

예외 처리(Exception Handling): 프로그램을 위한 보험처리, 잘못된 하나로 전체 시스템이 무너지는 결과를 방지하기 위한 기술적인 처리

예외 클래스: 예외를 만들 수 있는 클래스, java.lang.Throwable 클래스의 서브클래스들

JVM은 프로그램 실행 중 예외가 발생하면, 관련된 예외 클래스로부터 객체를 생성하여 예외를 발생시킨 메소드에 전달한다.

자바에서 예외 처리는 1) 예외가 발생한 메소드 내에서 처리하는 방법과 2) 예외를 자신을 호출한 메소드에 넘겨주는 방법이 있다.

  • try, catch, finally 메소드에서 예외 처리
    try, catch, finally 구문을 이용해 예외를 직접 처리한다.

      try{ // 예외가 발생할 가능성이 있는 코드
          // 조건없이 실행되는 문장, 예외 발생 가능성이 있는 범위를 지정하는 블록
          // 적어도 하나 이상의 catch를 가져야 한다.
          // 예외 발생 시 JVM은 즉각 수행을 중단하고 발생된 예외의 타입에 따라 적합한 catch 블록을 찾아 수행한다. 
      } catch(Exception e){ // 예외 발생 시 대안 처리
          // try 블록 바로 다음에 위치해야 한다. 
          // 예외타입은 반드시 java.lang.Throwable 클래스의 하위 클래스이어야 한다. 
      } finally{
          // 선택적, 예외 발생과 상관없이 무조건 수행되는 블록
          // 1) try 블록에서 예외가 발생되어 catch 블록이 수행되거나
          // 2) try 블록이 예외 발생 없이 수행이 끝났을 경우에도 수행 된다. 
          // ex) 파일이나 db를 닫을 때 사용
      }
    
  • throws, throw 호출한 메소드에 예외를 넘겨 예외 처리
    발생된 예외를 메소드 내에서 처리하지 않고, 호출한 메소드에 넘겨준다.

    throws: 메소드의 선언부에서 어떤 종류의 예외들이 던져질 것인지를 명시할 때 사용

      public void doSomething() throws 예외클래스 [, 예외클래스, ...] {
          ...
      }
    

    throw: 직접 예외 객체를 발생시켜 코드 바깥으로 예외를 던질 때 사용

      public void doSomething() throws 예외클래스 {
          try { ... }
          catch (Exception e) {
              throw new NullPointerException(); // 에러 메시지를 포함하지 않는 Exception 객체를 생성
              or 
              throw new NullPointerException("NullPointException 발생"); // 에러 메시지를 포함 하는 Exception 객체를 생성
          }
      }
    

자바가 제공하는 예외 계층 구조

자바는 발생할 수 있는 예외에 대해 java.lang 패키지에 예외 관련 클래스를 제공하고 있다. 자바의 모든 예외 관련 클래스는 java.lang.Throwable 클래스의 하위 클래스로 제공된다.

Exception의 두가지 종류

  • Checked Exception: 예외 처리를 하지 않으면 컴파일을 허락하지 않는 예외, 주로 외부 리소스와 통신하는 경우는 반드시 Checked Exception 이라고 생각하면 된다.
  • Unchecked Exception: 컴파일 시에 체크되지 않고, 실행(Runtime) 시에 발생하는 예외, 코드 로직에 의해 처리해야 하는 예외이다.
    ex) NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException, …

Exception과 Error의 차이는?

  • java.lang.Error 클래스: java.lang.Throwable 클래스로부터 상속된 클래스로 주로 하드웨어 관련 예외를 처리하는 클래스이다. Error 클래스의 예외는 프로그램에서 처리하지 않고 JVM에 맡겨진다.
    ex) 스택 오버플로우, 메모리 부족(OutOfMemoryError), JVM 동작 이상 발생, …

  • java.lang.Exception 클래스: java.lang.Throwable 클래스로부터 상속된 클래스이다. 이 중 java.lang.RuntimeException 클래스는 실행시간 예외들과 관련된 클래스들을 하위 클래스로 가지고 있으며, Error 클래스 예외처럼 일반적으로 프로그램에서 지정하지 않는다.
    ex) 입력 값이 오류, 네트워크 문제, JVM 자체에는 문제가 없는 상황

Exception 클래스에서 알야아 할 메소드

  • printStackTrace(): 발생한 Exception의 출처를 메모리상에서 추적하면서 결과를 알려준다. 예외가 발생한 위치를 정확히 화면에 출력해준다. 리턴 타입이 void이기 때문에 보이는 메시지를 다른 방식으로 응용할 수 없다는 불편함이 있다.

  • getMessage(): printStackTrace()가 상세한 내용이라면 getMessage()는 한 줄로 요약된 요약 메시지를 String으로 반환해준다. 간단하게 결과만 알고 싶을 때 사용한다.

  • getStackTrace(): StackTraceElement라는 객체들의 배열로 결과를 객체화시켜준다.

RuntimeException과 RE가 아닌 것의 차이는?

RuntimeException은 실행시간 예외들과 관련된 클래스들을 하위 클래스로 가지고 있다. Error 클래스 예외처럼 일반적으로 프로그램에서 지정하지 않는데, 이유는 예외 처리가 비효율적이기 때문이다. 이러한 예외들의 처리는 JVM에 맡기는 것이 더 효율적이다. 자바는 RuntimeException과 Error 클래스를 제외한 나머지 클래스와 관련된 예외는 프로그램에서 처리하도록 요구하고 있다.

RuntimeException 종류

  • ArrayIndexOutOfBoundsException: 배열을 참조하는 인덱스가 잘못된 경우
  • NullPointerException: Null 객체 참조했을 경우
  • ClassCastException: 적절치 못하게 Class를 형변환한 경우
  • ArithmeticException: 정수를 0으로 나누었을 경우

커스텀한 예외 만드는 방법

사용자 정의 예외(User Defined Exception)로 Exception 클래스를 상속해 클래스를 만든다.

public class UserDefinedException extends Exception {
    public UserDefinedException(String msg){
        super(msg);
    }
}

public void doSomething() throws UserDefinedException { // 내가 만든 예외 클래스 명시
    ...
    try {
        ...
    } catch (Exception e) {
        e.printStackTrace();
    }
    ...
    try {
        ...
    } catch (Exception e){
        e.printStackTrace();
        throw new UserDefinedException(e.getMessage()); // 내가 만든 예외 클래스의 객체를 만들어 예외를 던짐
    }
}

참고 서적

뇌를 자극하는 Java 프로그래밍
알기 쉽게 해설한 Java
열혈강의 객체 중심 Java


live-study with whiteship