[Java] 예외 처리
21. 예외처리
자바 예외 처리
- 자바는 프로그램 실행 중에 발생할 수 있는 예상치 못한 상황 즉, 예외(Exception)을 처리하기 위한 메커니즘을 제공한다.
- try, catch, finally, throw, throws
- 예외 처리가 필요한 이유
- 외부 서버와 통신 할 때 다양한 문제들이 발생한다.
- 외부 서버와의 연결 실패, 데이터 전송 문제
- 예외 처리를 사용하면 정상 흐름과 예외 흐름을 명확하게 분리할 수 있다.
- 외부 서버와 통신 할 때 다양한 문제들이 발생한다.
예외 계층
Object
: 예외도 객체이므로, 예외의 최상위 부모도Object
이다.Throwable
: 최상위 예외로 하위에Exception
과Error
가 있다.Error
: 메모리 부족, 심각한 시스템 오류와 같은 애플리케이션에서 복구 불가능한 시스템 예외이다.- 개발자는 이 예외를 잡으려고 하면 안됨
Exception
: 체크 예외- 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외
RuntimeException
을 제외한 하위 예외는 컴파일러가 체크하는 체크 예외이다.- 발생한 예외를 개발자가 명시적으로 처리해야한다.
- 처리하지 않으면 컴파일 오류가 발생한다.
RuntimeError
: 언체크 예외, 런타임 에러- 컴파일러가 체크하지 않는 언체크 예외
- 하위 예외는 모두 언체크 예외
- 발생한 예외를 명시적으로 처리하지 않아도 된다.
예외 기본 규칙
- 예외는 잡아서 처리하거나, 밖으로 던져야 한다.
- 자바
main()
밖으로 예외를 던지면 예외 로그를 출력하면서 시스템이 종료된다.
- 자바
- 예외를 잡거나 던질 때 지정한 예외뿐만 아니라 그 예외의 자식들도 함께 처리할 수 있다.
체크 예외
Exception
과 하위 예외 (RuntimeException
제외)- 체크 예외는 잡아서 처리하거나, 밖으로 던지도록 선언해야 한다.
public class Client { public void call() throws MyCheckedException { throw new MyCheckedException("ex"); } } public class MyCheckedException extends Exception { public MyCheckedException(String message) { super(message); } }
throw 예외
: 새로운 예외 발생- 예외는 객체이므로 객체를 new로 먼저 생성하고 예외를 발생시킨다.
throws 예외
: 발생시킨 예외를 메서드 밖으로 던질 때 사용한다.MyCheckedException
:Exception
예외를 상속받은 체크 예외super(message)
로 전달한 오류 메시지는Throwable
에 있는detailMessage
에 보관된다.getMessage()
를 통해 오류메세지를 조회 가능하다.
- 예외를 잡아서 처리하는 코드
public class Service { public void callCatch() { try { client.call(); } catch (MyCheckedException e) { //예외 처리 로직 System.out.println("예외 처리, message= " + e.getMessage()); } System.out.println("정상 흐름"); } } public class CheckedCatchMain { public static void main(String[] args) { Service service = new Service(); service.callCatch(); System.out.println("정상 종료"); } }
client.call()
에서MyCheckedException
예외가 발생하고, 그 예외를Service.callCatch()
에서 잡는다.- 예외 처리 시
try ~ catch(...)
를 사용해서 예외를 잡는다.try
코드 블럭에서 발생하는 예외를 잡아서catch
로 넘긴다.- 만약
catch
의 대상에 예외가 없으면 밖으로 던져야 한다. catch
에 예외 지정 시 하위 타입예외까지 모두 잡아준다.
- 예외를 밖으로 던지는 코드
public class Service { public void callThrow() throws MyCheckedException { client.call(); } } public class CheckedThrowMain { public static void main(String[] args) throws MyCheckedException { Service service = new Service(); service.callThrow(); System.out.println("정상 종료"); } }
throws
를 사용해서, 밖으로 던질 예외를 지정한다.Service.callThrow()
에서 예외를 처리하지 않고 밖으로 던졌기 때문에 예외가main()
까지 올라온다.main()
에서는 예외가 밖으로 던져져서 예외 정보와 스택 트레이스를 출력하고 프로그램이 종료된다.
- 체크 예외의 장단점
- 장점 : 개발자가 실수로 예외를 누락하지 않도록 컴파일러를 통해 문제를 잡아준다.
- 단점 : 모든 예외를 반드시 잡거나 던져야 해서 번거롭다.
언체크 예외
RuntimeException
과 하위 예외- 컴파일러가 예외를 체크하지 않는다.
- 예외를 던지는
throws
를 선언하지 않고 생략 가능하다. 생략한 경우 자동으로 예외를 던진다.public class Service { Client client = new Client(); public void callCatch() { try { client.call(); } catch (MyUncheckedException e) { //예외 처리 로직 System.out.println("예외 처리, message= " + e.getMessage()); } System.out.println("정상 로직"); } public void callThrow() { client.call(); } } public class UncheckedCatchMain { public static void main(String[] args) { Service service = new Service(); service.callCatch(); System.out.println("정상 종료"); } } public class UncheckedThrowMain { public static void main(String[] args) { Service service = new Service(); service.callThrow(); System.out.println("정상 종료"); } }
- 언체크 예외도 필요한 경우 예외를 잡아서 처리할 수 있다.
예외를 밖으로 던질 때는 체크 예외와 다르게
throws 예외
를 선언하지 않아도 된다.- 언체크 예외의 장단점
- 장점 : 신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다.
throws
생략 - 단점 : 체크예외는 컴파일러가 예외 누락을 잡아주지만 언체크 예외는 개발자가 실수로 예외를 누락할 수 있다.
- 장점 : 신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다.
김영한의 실전 자바 중급 1편을 참고하였습니다