Java

Java의 Exception Handling

정의

프로그램 실행 시 발생할 수 있는 예외 발생에 대비해 복구할 수 있는 코드를 작성하는 것

목적

프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것

예시

배열의 범위를 벗어난(ArrayIndexOutOfBoundsException), 값이 null이 참조변수를 참조(NullPointerException), 존재하지 않는 파일의 이름을 입력(FileNotFoundException) 등
이러한 것들은 경미한 오류여서 복구할 수 있는 수준이라는 것을 알 수 있습니다.
  • try catch 를 통해 예외를 직접 처리하는 방법이 있습니다.
  • throws 를 통해서 caller 에게 책임을 넘기는 방법이 있습니다.

특징

메소드

  • printStackTrace()
    • 예외 발생 당시의 호출 스택(Call Stack)에 있었던 메소드의 정보와 예외 메시지를 화면에 출력
  • getMessage()
    • 발생한 예외 클래스의 인스턴스에 저장된 메시지

스코프

예외 참조 변수의 스코프는 catch 블록 안

사용

처리방법

메소드 안에서 직접 처리

  • try catch 문
  • 멀티 catch 블록
    • | 를 사용하여
    • catch 블록 내 내용이 같으면 합칠 수 있음
    • 부모 관계 예외 클래스를 넣으면, 부모 예외 클래스만 넣는거와 동일
    • 자식 예외와 부모 예외가 동시에 올 수 없다
    • UncheckedException이랑 CheckedException가 동시에 올 수 없다
  • finally
    • 무조건 실행되어야하는 코드
  • try-with-resource
    • AutoCloseable 인터페이스를 구현하는 FileWriter 같은 클래스는 이 문법을 사용할 수 있음
    • AutoCloseable이므로 당연히 close 할 필요 없음

예외 넘기기: 발생한 예외를 직접 처리하지 않고 메소드를 호출한 곳에서 처리

  • throw
    • 예외 발생시키기
  • throws
    • 자신을 호출한 곳으로 예외를 던지는 것
    • 메소드 뒤에 throws 붙임
    • 체크드 예외만 선언
    • 폭탄 돌리기로 표현
      • 결국에 누군가가 휴지통에 폭탄을 던져 넣어야함

예외 되던지기

  • 예외 처리 후, 다시 예외를 발생시킴
  • 직접 처리 + 예외 넘기기
  • 예외를 여러번 처리 가능

무시하기

  • 예외를 은폐

예외 생성

사용자 정의 예외 만들기

  • 조상은 Exception과 RuntimeException 중에서 선택
  • 생성자 만들기
    • 생성자(String msg) { super(msg) //조상 클래스의 생성자 호출 }

연결된 예외

한 예외가 다른 예외를 발생시키는 것
여러 예외를 하나로 묶어서 다루기 위함
  • 세부적인 사항을 포괄적인 사항으로 포함시킬 때
    • 한 예외가 다른 예외를 발생
    • 예외 A가 예외 B를 발생시키면, A는 B의 원인 예외(cause exception)
      • 프로그램을 설치하다가 저장 공간 부족 오류를 발생한다고 하자
        • 이 예외를 잡아서
        • 설치 오류 예외를 생성
          • 설치 오류 예외에 initCause(저장 공간 부족 오류)를 원인 예외로 등록하고
          • 설치 오류 예외를 던진다.
  • checked 예외를 unchecked 예외로 변경하고 싶을 때
    • 예외 필수 처리 → 예외 선택 처리로 변경
      • Checked 예외인 IOException을 Unchecked 예외인 RuntimeException으로 감싸 Unchecked 예외로 바꾼다.
    • try-catch문 사용을 줄일 수 있음
 

Spring의 Exception Handling

HandlerExceptionResolver

면접 질문

  • Exception Handling의 정의와 목적
    • 프로그램 실행 시 발생할 수 있는 예외 발생에 대비해 복구할 수 있는 코드를 작성하는 것
    • 프로그램의 비정상 종료를 막고, 정상적인 실행상태를 유지하는 것
  • Exception Handling의 방법
    • 메소드 안에서 직접 처리
      • try-catch 문
        • catch
          • 부모 Exception 클래스를 먼저 두면 그 자식 Exception 클래스를 다 잡아감
          • 따라서, 자식 Exception 클래스를 앞에 두어야함
        • 멀티 catch 블록
          • 자식 예외와 부모 예외가 동시에 올 수 없다
          • UncheckedException이랑 CheckedException가 동시에 올 수 없다
      • finally
      • try-with-resource
        • finally에 close 코드를 작성하지 않아도 되므로, 하고자하는 로직에 집중할 수 있다.
        • AutoCloseable 인터페이스를 구현하는 클래스는 이 문법을 사용할 수 있음
        • AutoCloseable이므로 close 할 필요 없음
    • 예외 넘기기: 발생한 예외를 직접 처리하지 않고 메소드를 호출한 곳에서 처리
      • throw
        • 예외 발생시키기
      • throws
        • 자신을 호출한 곳으로 예외를 던지는 것
        • 메소드 뒤에 throws 붙임
        • 체크드 예외만 사용
    • 예외 되던지기
      • 예외 처리 후, 다시 예외를 발생시킴
      • 예외 직접 처리 + 예외 넘기기
      • 예외를 여러번 처리 가능
    • 무시하기
      • 예외를 은폐
  • 사용자 정의 예외
    • 생성 방법
      • 조상은 Exception과 RuntimeException 중에서 선택
      • 생성자 만들기
        • 생성자(String msg) { super(msg) //조상 클래스의 생성자 호출 }
    • 연결된 예외
      • 한 예외가 다른 예외를 발생시키는 것
        여러 예외를 하나로 묶어서 다루기 위함
      • 세부적인 사항을 포괄적인 사항으로 포함시킬 때
        • 한 예외가 다른 예외를 발생
        • 예외 A가 예외 B를 발생시키면, A는 B의 원인 예외(cause exception)
          • 프로그램을 설치하다가 저장 공간 부족 오류를 발생한다고 하자
            • 이 예외를 잡아서
            • 설치 오류 예외를 생성
              • 설치 오류 예외에 initCause(저장 공간 부족 오류)를 원인 예외로 등록하고
              • 설치 오류 예외를 던진다.
      • checked 예외를 unchecked 예외로 변경하고 싶을 때
        • 예외 필수 처리 → 예외 선택 처리로 변경
          • Checked 예외인 IOException을 Unchecked 예외인 RuntimeException으로 감싸 Unchecked 예외로 바꾼다.
        • try-catch문 사용을 줄일 수 있음
  • Stack Trace
    • 프로그램이 시작된 시점부터 현재 위치 까지의 메서드 호출 목록
    • 예외가 어디서 발생했는지 알려주기 위해 JVM이 자동으로 생성
    • 발생된 시점부터 프로그램이 시작된 시점까지 거슬러 올라가면서 출력하기 때문에 먼저 실행 된 메서드가 아래쪽에 위치
    • printStackTrace()
  • 예외처리의 일관성을 유지할수 있을까? 그리고 다른 프로그래머가 그것을 알 수 있는 방법은?
    • 자체적으로 발생하는 예외는 @ExceptionHandler으로 적절한 Error Response를 만들고
    • 비즈니스 요구사항에 예외일 경우 BusinessException 만들고 이를 상속하여 통일성 있게 처리
    • 에러 코드enum 타입으로 한 곳에서 관리 Common과 각 도메인별로 관리하는 것이 효율적
  • try-catch 효율적 사용법
      1. try catch를 최대한 지양
      1. try catch로 에러를 먹고 주는 코드는 지양(로그라도 추가)
      1. try catch를 사용하게 된다면 구체적인 Exception을 발생시키는 것이 좋다.

출처

Java의 정석 3판 남궁 성