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 효율적 사용법
try catch
를 최대한 지양try catch
로 에러를 먹고 주는 코드는 지양(로그라도 추가)try catch
를 사용하게 된다면 구체적인 Exception을 발생시키는 것이 좋다.
출처
Java의 정석 3판 남궁 성