김영한 선생님의 자바 중급을 듣고 정리한 내용입니다.
1. 자바 예외 처리1 - 예외 계층
Java는 프로그램 실행 중에 발생할 수 있는 예상치 못한 상황, 즉 예외(Exception)을 처리하기 위한 메커니즘을 제공한다.
이는 프로그램의 안정성과 신뢰성을 높이는데 중요한 역할을 한다.
try, catch, finally, throw, throws
1.1. 예외 계층 그림
- Object : Java에서 기본형을 제외한 모든 것은 객체이고 예외(Exception)도 객체이다. 모든 객체의 최상위 부모는 Object이므로 예외의 최상위 부모도 Object이다.
- Throwable : 최상위 예외이다. 하위에 Exception과 Error가 있다.
- Error : 메모리 부족이나 심각한 시스템 오류와 같이 애플리케이션에서 복구가 불가능한 시스템 예외이다.
- Exception : 체크 예외
- 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외이다.
- Exception과 그 하위 예외는 모두 컴파일러가 체크하는 체크 예외이다. 단, RuntimeException은 예외로 한다.
- RuntimeException : 언체크 예외, 런타임 예외
- 컴파일러가 체크하지 않는 언체크 예외이다.
- RuntimeException과 그 자식 예외는 모두 언체크 예외이다.
- RuntimeException의 이름을 따라서 RuntimeException과 그 하위 언체크 예외를 런타임 예외라고 많이 부른다.
1.1.1. 체크 예외 vs 언체크 예외(런타임 예외)
체크 예외는 발생한 예외를 개발자가 명시적으로 처리해야 한다. 그렇지 않으면 컴파일 오류가 발생한다.
언체크 예외는 개발자가 발생한 예외를 명시적으로 처리하지 않아도 된다.
2. 자바 예외 처리2 - 예외 기본 규칙
예외 ~= 폭탄 돌리기
→ 예외가 발생하면 잡아서 처리하거나, 처리할 수 없다면 밖으로 던져야 한다.
2.1. 예외 처리
[1] Main은 Service를 호출한다.
[2] Service는 Client를 호출한다.
[3] Client에서 예외가 발생한다.
[4] Client에서 예외를 처리하지 못하고 밖으로 던진다. →여기서 Client의 밖은 Client를 호출한 Service를 뜻한다.
[5] Service에 예외가 전달된다. Service에서 예외를 처리했다. → 이후에는 애플리케이션 로직이 정상 흐름으로 동작한다.
[6] 정상 흐름을 반환한다.
2.2. 예외 던짐
2.2.1. 예외 규칙 2가지
[1] 예외는 잡아서 처리하거나 밖으로 던져야 한다.
[2] 예외를 잡거나 던질 때 지정한 예외뿐만 아니라 그 예외의 자식들도 함께 처리할 수 있다.
→ 예를 들어서 Exception을 catch로 잡으면 그 하위 예외들도 모두 잡을 수 있다.
→ 예를 들어서 Exception을 throws로 던지면 그 하위 예외들도 모두 던질 수 있다.
참고 : 예외를 처리하지 못하고 계속 던지면 어떻게 되는 것인가? main() 밖으로 예외를 던지면 예외 로그를 출력하면서 시스템이 종료된다.
3. 자바 예외 처리3 - 체크 예외
Exception과 그 하위 예외는 모두 컴파일러가 체크하는 체크 예외이다. 단 RuntimeException은 예외로 한다.
체크 예외는 잡아서 처리하거나 또는 밖으로 던지도록 선언해야 한다.
→ 그렇지 않으면 컴파일 오류가 발생한다.
3.1. 체크 예외 전체 코드
3.1.1. MyCheckedException
예외 클래스를 만들기 위해서는 Exception 클래스를 상속받으면 된다.
Exception 클래스를 상속받으면 체크 예외가 된다.
3.1.2. Client
throw 키워드 : 새로운 예외를 발생시키는 코드이다. 예외도 클래스이기 때문에 new 키워드를 사용하여 생성하고 예외를 발생시켜야 한다.
throws 예외 : 발생시킨 예외를 밖으로 던질 때 사용한다.
3.1.3. Service
callCatch : try - catch 구문으로 예외를 직접 잡아서 처리한다.
callThrows : throws 키워드로 체크 예외를 밖으로 던진다.
3.1.3. Check 예외
- super(message)로 전달한 메시지는 Throwable에 있는 detailMessage에 보관된다.
- getMessage() 메서드로 detailMessage 인스턴스 변수를 조회할 수 있게 된다.
- super(message)로 전달한 메시지는 Throwable에 있는 detailMessage에 보관된다.
- getMessage() 메서드로 detailMessage 인스턴스 변수를 조회할 수 있게 된다.
3.2. 예외를 잡아서 처리 (catch)
1. Client.call()에서 MyCheckedException 예외가 발생
2. 그 예외를 Service.callCatch()에서 잡는다.
catch는 해당 타입과 그 하위 타입을 모두 잡을 수 있다.
→ catch에서 MyCheckedException의 상위 타입인 Exception을 적어주어도 MyCheckedException을 잡을 수 있다.
→ 예외도 객체이기 때문에 다형성이 적용된다.
3.3. 예외를 처리 하지 않고 던지기 (throws)
- Service.callThrows() 메서드에서 예외를 처리하지 않고 밖으로 던졌기 때문에 main() 메서드까지 올라온다.
- main()에 있는 service.callThrows() 메서드 다음에 있는 정상 종료 구문이 출력되지 않는다.
- 예외가 main() 밖으로 던져지면 예외 정보와 스택 트레이스를 출력하고 프로그램이 종료된다.
3.3.1. 체크 예외를 밖으로 던지는 경우에도 해당 타입과 그 하위을 모두 던질 수 있음
public void callThrows() throws Exception {
client.call();
}
→ MyCheckedException의 상위 타입인 Exception을 적어주어도 MyCheckedException을 던질 수 있다.
→ throws에 지정한 타입과 그 하위 타입 예외를 밖으로 던진다.
→ 예외도 객체이기 때문에 다형성이 적용된다.
3.4. 체크 예외 정리
3.4.1. 장점
개발자가 실수로 누락하지 않도록 컴파일러를 통해 문제를 잡아주는 훌륭한 안전 장치이다.
이를 통해 개발자는 어떤 체크 예외가 발생하는지 쉽게 파악할 수 있다.
3.4.2. 단점
실제로는 개발자가 모든 체크 예외를 반드시 잡거나 던지도록 처리해야 하기 때문에 너무 번거로운 일이 된다.
크게 신경쓰고 싶지 않은 예외까지 모두 챙겨야 한다.
3.4.3. 정리
체크 예외는 잡아서 직접 처리하거나, 밖으로 던지거나 둘 중 하나를 개발자가 직접 명시적으로 처리해야 한다.
그렇지 않으면 컴파일 오류가 발생한다.
4. 자바 예외 처리4 - 언체크 예외
- RuntimeException과 그 하위 예외 : 언체크 예외로 구분된다.
- 컴파일러가 예외를 체크하지 않는다는 뜻이다.
- 언체크 예외는 체크 예외와 기본적으로 동일하다. 차이가 있다면 예외를 던지는 throws를 선언하지 않고 생략할 수 있다. 생략한 경우 자동으로 예외를 던진다.
4.1. 체크 예외 vs 언체크 예외
- 체크 예외 : 예외를 잡아서 처리하지 않으면 항상 throws 키워드를 사용해서 던지는 예외를 처리해야 한다.
- 언체크 예외 : 예외를 잡아서 처리하지 않아도 throws 키워드를 생략할 수 있다.
4.2. 언체크 예외 예시
4.2.1. callCatch()
4.2.2. callThrow()
4.3. 언체크 예외의 장단점
언체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외를 생략할 수 있다.
이것 때문에 장단점이 존재한다.
4.3.1. 장점
신경쓰고 싶지 않은 언체크 예외를 무시할 수 있다.
체크 예외의 경우 처리할 수 없는 예외를 밖으로 던지려면 항상 throws 예외를 선언해야 하지만 언체크 예외는 이 부분을 생략할 수 있다.
4.3.2. 단점
언체크 예외는 개발자가 실수로 예외를 누락할 수 있다.
반면에 체크 예외는 컴파일러를 통해 예외 누락을 잡아준다.
4.3.3. 정리
체크 예외와 언체크 예외의 차이는 예외를 처리할 수 없을 때 예외를 밖으로 던지는 부분에 있다.
이 부분을 필수로 선언해야 하는가 생략할 수 있는가의 차이다.
'Programming > Java' 카테고리의 다른 글
[Java] 김영한의 자바 중급 2편 #1 - 제네릭 (1) | 2024.11.03 |
---|---|
[Java] 김영한의 자바 중급 1편 #10 - 예외처리 실습 (0) | 2024.10.15 |
[Java] 김영한의 자바 중급 1편 #8 - 중첩 클래스, 내부 클래스 - 2 (0) | 2024.10.04 |
[Java] 김영한의 자바 중급 1편 #7 - 중첩 클래스, 내부 클래스 - 1 (0) | 2024.10.04 |
[Java] 김영한의 자바 중급 1편 #6 - 날짜와 시간 라이브러리 (0) | 2024.09.30 |