JAN's History
자바의 정석 - CH8 예외처리 본문
1. 프로그램 오류
컴파일 에러(compile-time error) : 컴파일 할 때 발생하는 에러
런타임 에러(runtime error) : 실행할 때 발생하는 에러
논리적 에러(logical error) : 작성 의도와 다르게 동작



- 에러는 어쩔 수 없지만 예외는 처리하자.


=> 미약한 에러를 처리하기 위한 것이 예외처리.



1. try문에 들어와서 예외가 발생할 때까지 실행하다가
2. 예외가 발생하면 catch문을 실행한다.
3. 예외를 처리할 catch 블럭이 없으면 프로그램 비정상적으로 종료.
왼쪽은 예외가 발생하지 않았으므로 그냥 통과.
오른쪽은 0을 0으로 나누는 것이 예외이므로 catch문으로 출력.


catch (Exception e)는 모든 예외의 최고 조상이기 때문에 모든 예외를 처리할 수 있다.
=> 마지막에 와야함.
오른쪽 사진 처럼 ArithmeticException이 없어도 모든예외의 최고 조상이 있기 때문에 예외 처리가능.
printStackTrace() : 예외 발생 당시 호출 스택에 있던 메서드의 정보와 예외 메시지를 화면에 출력한다.
getMessage() : 발생한 예외클래스의 인스턴스에 저장된 메시지를 얻을 수 있다.

예외가 발생하면 예외 객체가 만들어지고 예외 객체에는 예외에 대한 정보가 들어있다.
그것을 볼 수 있는 메서드가 printStackTrace(), getMessage() 이 외에도 많은데 이 두개만 소개!

=> 코드의 중복을 제거하기 위함.


=> 부모 자식관계에서는 안된다.
catch블럭 체크할 때 ParentException을 하면 instanceof를 체크하기 때문에 굳이 ChildException을 할 필요 X
+instanceof : 참조 변수의 형변환이 가능한지 확인하는 것 (조상인지 확인)
=> 예외처리를 멀티 catch블럭을 사용할 때 공통 멤버만 사용 가능 (드문 경우)
Exception A | ExceptionB를 예외처리 하기로 해놓고 e.methodA();를 하면 Exception A에만 적용되는 거니까 당연히 에러
+ 정 사용하고 싶다면 밑 if else문으로 사용.
1-2 예외 발생시키기


1. 예외를 Exception으로 예외 객체를 만든 후 throw e;를 통해 예외 생성.
2. catch(Exception e)가 throw를 잡음. 이후에 getMessage()를 통해 메시지를 전달.
+ catch 블럭이 없었다면 비정상종료가 되었을 것.
checked 예외 : 컴파일러가 예외 처리 여부를 체크(예외 처리 필수)
=> Exception과 자손
unchecked 예외 : 컴파일러가 예외 처리 여부를 체크 안함(예외 처리 선택)
=> RuntimeExcetpion과 자손


왼쪽은 Exception은 체크드 예외이기 때문에 컴파일 자체에서 에러가 발생
=> 예외처리 필수
오른쪽 RuntimeException()은 언체크드 예외이기 때문에 컴파일은 되지만 비정상종료.

1-3 메서드에 예외 선언하기
- 예외를 처리하는 방법 : try-catch문(직접 처리), 예외 선언하기(예외 떠넘기기=알리기), 은폐하기(빈 catch블럭을 사용)
- 메서드가 호출 시 발생가능한 예외를 호출하는 쪽에 알리는 것

// 오버라이딩의 3가지 규칙
1. 선언부 일치
2. 접근 제어자를 좁게 설정 X
3. 조상보다 많은 예외 선언 X => Exception이 가장 많은 예외인 것.

IllegalMonitorStateExceptio은 언체크드라서 위에 적혀있지 않은 거고 InterriptedException은 체크드라서 적혀있는 것
=> 예외처리 필수인 것들만 선언한다. 언체크드 예외는 선언하지 않는다. (최소한으로 선언)

main 메서드에서 method1을 출력하고, method1에서 method2를 출력한다.
method2에서는 Exception을 던지는데 catch문이 없으므로 method1에게 토스한다.
method1도 catch문이 없으므로 main메서드에세 토스하고, main메서드에도 catch문이 없으므로
JAVA의 예외처리기에게 토스한다.
그리하여 출력 결과물에도 예외가 발생한 정보가 나타나있다.
=> 이렇게 떠넘기기만 해선 예외 처리가 될 수 없다. try-catch문이 있어야한다.
=> 예외를 선언하는 것과 떠넘기는 것의 차이점을 알아두자.

throws Exception이 있는 걸 보니 떠넘긴다는 뜻.
"파일이름이 유효하지 않습니다."라는 메시지를 가진 예외를 떠넘겨서 try-catch문으로 해결.

=> try-catch문을 예외가 발생한 곳에서 선언할 수도 있고 메서드를 호출한 쪽에서 예외를 선택할 수 있다.
작업을 시킨 메서드가 수행하는 것이 맞는지 Vs 작업을 수행하는 메서드가 수행하는 것이 맞는지를 선택해야함.
finally 블럭 : 예외 발생 여부와 관계없이 수행되어야하는 코드를 넣는다.


=> 코드의 중복제거
예외 처리가 성공하던 실패하던 무조건 실행!
1-4 사용자 정의 예외 만들기
- 우리가 직접 예외 클래스를 정의할 수 있다.
- 조상은 Exceptoin(사용자가 발생시킨 예외, 필수처리)과
RuntimeException(프로그래머의 실수로 발생시킨 예외, 선택처리)중에서 선택한다.

=> Exception은 필수처리라서 try-catch문이 꼭 나와야하기 때문에 될 수 있으면 RuntimeException을 선택하는 것이 좋다.
+ 보통은 Exception을 조상으로 사용
=> 그리고 string 매개변수가 있는 생성자를 넣고 조상 클래스의 생성자를 호출해야한다.
= = > 그러면 사용자 정의 예외를 직접 정의하게 된다.
예외 되던지기 : 예외를 처리한 후에 다시 예외를 발생시키는 것
- 호출한 메서드와 호출된 메서드 양쪽 모두에서 예외처리하는 것

=> 처리를 2번하게 되는 것, 분담처리 해야할 때 사용.
예외 처리 후 throw로 다시 예외를 발생시킨다.
예외 처리하는 방법 3가지
1. 직접 처리하는 방법 : 메서드를 만든 곳에서 처리.
2. 토스해서 처리 : 메서드를 만든 곳에서 말고 호출한 곳에서 처리
3. 분담해서 처리 : 양쪽에서 처리
1-5 연결된 예외
- 한 예외가 다른 예외를 발생시킬 수 있다.
- 예외 A가 예외 B를 발생시키면 A는 B의 원인예외다

.
Throwable은 최고조상 격이라서 Exception과 같다고 생각하면 된다.
1. startInstall()에서 저장공간 부족인 SpaceException 예외가 발생했다.
2. catch문으로 SpaceException (=예외 A)가 들어가는데 안에서 또 새로운 예외를 만들었다.
3. 그리고 그 둘을 initCause로 묶어 연결시켰다. InstallException안에 SpaceException가 있는 격.
4. 그리고 다시 throw ie;로 예외를 main으로 던졌다.
연결된 예외를 사용하는 이유
1. 여러 예외를 하나로 묶어 사용하기 위해


왼쪽의 try-catch문의 결과값은 단순히 "설치할 공간이 부족하다"고만 보여준다.
=> 연결된 예외가 없어 spaceException을 사용하면 공간이 없다고만 출력할 수 밖에 없다.
오른쪽의 try-catch문의 결과값은 "설치 중 예외 발생, 설치할 공간이 부족합니다."를 보여준다.
=> lnstallException이라는 큰 예외 객체를 생성해서 그 안에 ie.initCause(e)로 둘을 연결시켜주었다. (연결하는 작업만 함)
이 때 "설치 중 예외 발생"을 출력시켰다.
=> 그리고 다시 throw로 예외를 전달해 try-catch문을 통해 "설치할 공간이 부족합니다" 를 출력시켰다.
= = > 대략정보와 세부정보 두가지를 제공하여 이해하기 쉽다.
= = > 예외처리가 간단해진다.
2. checked예외(Exception과 자손, 필수처리)를 uncheked예외(RuntimeException과 자손, 선택처)로 변경하려 할 때

MemoryException 은 Exception의 자손으로 필수처리 대상인데,
이를 선택처리로 바꾸고 싶다면 RuntimeException과 연결시키면 된다.
throw new RuntimeException(new MemoryException())이 RuntimeException의 원인예외로 등록된 것이다
= initCause()와 동일
위에서는 둘다 필수처리 예외이고 아래는 MemoryException은 RuntimeException의 원인 예외가 되어 선택예외가 되었다.
= = > 필수 예외가 되면 try-catch를 꼭 써야하지만 RuntimeException가 되면 try-catch을 쓰지 않아도 되기 때문에 사용.
연결된 예외 : 어떤 예외를 다른 예외로 감싸는 것
언제 사용 ? : 세부적인 예외를 포괄적인 예외로 감쌀 때, checked를 unchcked로 변경할 때.
'자바' 카테고리의 다른 글
| 자바의정석 CH10 날짜와시간 & 형식 (0) | 2023.04.17 |
|---|---|
| 자바의 정석 - CH9 lang 패키지 (0) | 2023.04.14 |
| 자바의 정석 - CH7 객체지향 언어 2 - 3 (0) | 2023.04.12 |
| 자바의 정석 - CH7 객체지향 언어 2 - 2 (0) | 2023.04.11 |
| 자바의 정석 - CH7 객체지향 언어 2 - 1 (0) | 2023.04.10 |