목표
자바의 예외 처리에 대해 학습하세요.
학습할 것
- Exception과 Error의 차이
- 예외클래스
- 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
- 자바가 제공하는 예외 계층 구조
- RuntimeException과 RE가 아닌 것의 차이는?
- 커스텀한 예외 만드는 방법
예외란? (Exception과 Error의 차이)
먼저 오류(Error)와 예외(Exception)의 개념을 정리하자
오류(Error)는 시스템에 비정상적인 상황이 생겼을 때 발생한다. 이는 시스템 레벨에서 발생하기 때문에 심각한 수준의 오류이다. 따라서 개발자가 미리 예측하여 처리할 수 없기 때문에, 애플리케이션에서 오류에 대한 처리를 신경 쓰지 않아도 된다.
오류가 시스템 레벨에서 발생한다면, 예외(Exception)는 개발자가 구현한 로직에서 발생한다. 즉, 예외는 발생할 상황을 미리 예측하여 처리할 수 있다. 예외는 개발자가 처리할 수 있기 때문에 예외를 구분하고 그에 따른 처리 방법을 명확히 알고 적용하는 것이 중요하다.
예외클래스

위 그림은 예외클래스 구조이다. 모든 예외클래스는 Throwable 클래스를 상속받고 있다.
Throwable을 상속받는 클래스는 Error와 Exception이 있다. Error는 시스템 레벨의 심각한 수준의 에러이기 때문에 시스템에 변화를 주어 문제를 처리해야 하는 경우가 일반적이고, Exception은 개발자가 로직을 추가하여 처리할 수 있다.
Exception은 수많은 자식 클래스를 가지고 있다. 그 중 RuntimeException을 주목해야 한다.
RuntimeException은 CheckedException과 UncheckedException을 구분하는 기준이다.
Exception의 자식 클래스 중 RuntimeException을 제외한 모든 클래스는 CheckedException이며, RuntimeException과 그의 자식 클래스들을 UncheckedException이라 부른다.
Checked Exception | Unchecked Exception | |
처리여부 | 반드시 예외를 처리해야 함 | 명시적인 처리를 강제하지 않음 |
확인시점 | 컴파일 단계 | 실행단계 |
예외발생 시 트랜잭션 처리 | roll-back 하지 않음 | roll-back 함 |
대표 예외 | Exception의 상속받는 하위 클래스 중 Runtime Exception을 제외한 모믄 예외 ex) IOException, SQLException |
RuntimeException 하위 예외 ex) NullPointerException, IllealArgumentException, SystemException, IndexOutOfBoundException |
Checked Exception과 Unchecked Exception의 가장 명확한 구분 기준은 '꼭 처리를 해야 하느냐'이다.
Checked Exception이 발생할 가능성이 있는 메소드라면 반드시 로직을 try/catch로 감싸거나 throw로 던져서 처리해야 한다. 반면 Unchcked Exception은 명시적인 예외처리를 하지 않아도 된다. 이 예외는 피할 수 있지만 개발자가 부주의해서 발생하는 경우가 대부분이고, 미리 예측하지 못했던 상황에서 발생하는 예외가 아니기 때문에 굳이 로직으로 처리를 할 필요가 없도록 만들어져 있다.
자바에서 예외 처리 방법 (try, catch, throw, throws, finally)
자바는 프로그램 실행중에 발생할 수 있는 예외 처리문을 제공한다.
자바 예외 처리 방법
- 메소드 내에서 직접 처리하는 방법
- 예외가 발생한 메소드를 호출한 곳으로 예외 객체를 넘겨주는 방법
- 사용자 정의 예외를 생성하여 처리하는 방법
try, catch


기본적으로 try-catch 문에서 예외가 발생한 경우와 발생하지 않았을 때의 흐름이 다르다.
위와 같이 예외가 발생하지 않았을 경우 catch 문 블록은 실행되지 않는다.


위와 같이 일부러 1/0 연산을 이용해서 에러를 발생시킨 경우 에러 발생 시 catch 블록을 실행시키는 걸 확인할 수 있다.
catch블록은 예외가 발생하면 발생한 예외에 해당하는 클래스의 인스턴스가 만들어진다.
예외가 발생한 문장이 try블럭에 포함되어 있다면, 이 예외를 처리할 수 있는 catch블럭이 있는지 찾게된다.
finally


finally 블럭은 try 블럭 코드의 완료 방식과 상관 없이 try 블럭이 일부만 실행되더라도 finally 블럭이 실행됩니다.
중간에 catch 블럭으로 빠지더라도 finally 블럭이 실행됩니다.
throw


throw는 특정 시점에 예외를 던져서 호출한 곳에 예외를 알리는 것입니다.
throws

이 메소드에서 예외 처리를 하지 않고 호출하는 메소드로 예외를 전파시키고 싶다면 사용할 수 있는 것이 바로 throws입니다. doCheckedException() 메소드에서 Exception() 메소드는 Checked Exception이기 때문에 try catch 문으로 예외 처리를 해주어야 하지만 throws를 통해서 상위 메소드에게 예외 처리를 전파시킨 경우입니다. 그러기 때문에 processException() 메소드에서 예외처리를 해줘야한다고 IDE에서 경고하고 있습니다.

위와 같이 상위 메소드로 예외를 전파시킨 걸 확인할 수 있습니다.
try-with-resources

리소스를 사용하고 닫아야 할 경우 finally 문에서 close()를 이용해서 자원을 해제합니다. 자원을 해제하지 않으면 메모리 누수가 발생할 수 있기 때문입니다. 하지만 위와 같이 사용할 경우 문제점이 몇가지 있었습니다.
- 자원 처리를 위해 InputStream 객체를 상단에 null로 선언이 필요하다.
- 개발자는 잊지말고 finally 에서 자원해제를 해줘야 한다.
- is.close() 메소드는 Checked Exception을 던지고 있기 때문에 예외 처리가 필요하다.
위와 같은 문제를 해결하기 위해서 java 7 이상에서는 try-with-resource 문법을 통해서 해결하였습니다.

try 키워드 뒤에 괄호 안에 자원 해제가 필요한 객체를 넣어 줌으써 자동으로 자원을 해제할 수 있습니다.
보다 훨씬 코드 가독성도 좋아졌습니다.
커스텀한 예외 만드는 방법
기존의 정의된 예외 클래스 외에 필요에 따라 개발자가 새로운 예외 클래스를 정희하여 사용할 수 있습니다.
커스텀한 Checked Exception 예외를 만들고 싶다면 Exception을 상속 받아서 만들고, Unchecked Exception 예외를 만들고 싶다면 RuntimeException을 상속 받아서 생성합니다.



기존의 예외 클래스는 주로 Exception을 상속받아서 Checked Exception으로 작성하는 경우가 많았다고 한다. 요즘은 예외처리를 선택적으로 할수 있도록 RuntimeException을 상속받아서 작성하는 쪽으로 바뀌어가고 있다고 한다. Checked Exception은 반드시 예외처리를 해주어야 하기 때문에 불필요한 경우에도 try-catch문을 넣어 코드가 복잡해지기 때문이다.
참조
Java 예외(Exception) 처리에 대한 작은 생각
일상생활에서도 기본적인 것은 고민하지 않고 습관처럼 사용하는 경우가 있다. 초급 개발자인 나에게 ‘예외(Exception)’이 바로 그런 것이었다. 처음 JAVA수업 때 강사님께 "왜 로직을 try문으로
www.nextree.co.kr
- yadon079.github.io/2021/java%20study%20halle/week-09
9주차 과제: 예외 처리. :: 개발자 한선우
해당 글을 백기선 님의 자바 스터디 9주차 과제를 공부하고 공유하기 위해서 작성되었습니다.
yadon079.github.io
'JAVA > Study' 카테고리의 다른 글
백기선님 자바 스터디 12주차 (0) | 2021.02.06 |
---|---|
백기선님 자바 스터디 11주차 - Enum (0) | 2021.01.31 |
백기선님 자바 스터디 1주차 (0) | 2021.01.10 |
백기선님 자바 스터디 8주차 - Interface (0) | 2021.01.10 |
백기선님 자바 스터디 7주차 (0) | 2020.12.27 |