예외 정의, 예외 발생 가능성 알림, 예외 핸들링 을 통해 적절하게 예외 처리를 진행 할 수 있다.-예외 처리 예시
// 예외 클래스를 만들어서 예외를 정의!!
public class OurBadException extends Exception {
public OurBadException() {
super("위험한 행동을 하면 예외처리를 꼭 해야함!!");
}
}
위 코드를 통해 우리만의 예외를 정의한 것이다.
모든 예외는 Exception을 상속받고 있으며 세세한 예외를 우리가 핸들링하기 위해 상속받아서 사용하는 것이다.
위 경우 super(); 를 통해 부모의 생성자를 가져와서 처리하였다.
package week04.sample01;
public class OurClass {
private final boolean just = true;
// throws
public void thisMethodIsDangerous() throws OurBadException{
// 위험하다는 flag 를 달아준 것
if(just){
throw new OurBadException();
// 항상 예외가 발생한다.
}
}
}
예외가 발생가능한 메서드를
throws를 통해 flag 를 세운다.
(해당하는 예외가 발생할 수 있다는 것을 알리기 위함)
예외를 발생하기위해서는throw를 사용할 수 있다. (둘이 햇갈리지 말기)
위 코드는 무조건 예외가 발생하도록 유도하였다. (일부로)
public class StudyException {
public static void main(String[] args) {
OurClass ourClass = new OurClass();
try{
ourClass.thisMethodIsDangerous();
}catch(OurBadException e){ // e 를 통해 인스턴스화 (보통 e)
System.out.println(e.getMessage());
// 우리가 예외 처리 생성시 super를 통해 등록한 메시지
}
finally {
// 무조건 실행
System.out.println("우리는 방금 예외를 핸들링 함, ");
}
}
}
try-catch-finally문을 사용하였다.
try는 예외를 포함하며 예외 발생 시 catch 문을 실행 그렇지 않으면 진행 됨
finally는 예외가 발생을 하던지 하지 않던지 무조건 실행되는 문 (생략 가능)
컴파일시 vs 런타임시 (예측 불가)
예외 클래스 또한 Object 클래스로 부터 상속받아서 사용한다.
그 클래스가 Throwable 클래스로서 이 클래스의 자식으로
Error 와 Exception 클래스가 있다.
그리고 각 클래스는 각각 IOError 클래스 (입출력), RuntimeException 클래스와 같이 구분되어 처리된다.

참고로
RuntimeException을 상속한 예외들 ==>UncheckedException
그렇지 않은 예외들 ==>CheckedException
으로 구현되어 있다.

위 처럼 실행되면서 발생하는 예외는
RuntimeException을 상속 받는다.
"이미 수많은 예외가 구현되어 있고 이걸 다 외울 필요는 없다. 우리가 필요한 예외가 없는 경우 custom 하게 정의하여 사용하면 된다."
-initCause() : 지정된 예외를 원인 예외로 등록하는 메서드
-getCause : 원인 예외를 반환하는 메서드
=> 왜 예외를 연결하나? :
1) 여러 가지 예외를 하나의 큰 분류 예외로 묶어서 다루기 위함
2) checked exception 을 unchecked exception으로 포장(wrapping) 하는데 유용하게 사용되기도 한다. (컴파일 시간 => 런타임시간)
예시 :
package week04.sample02;
// 연결된 예외
public class Main {
public static void main(String[] args) {
try {
// 예외 생성
NumberFormatException ex = new NumberFormatException("가짜 예외이유");
// 원인 예외 설정(지정한 예외를 원인 예외로 등록)
ex.initCause(new NullPointerException("진짜 예외이유"));
// 예외를 직접 던집니다.
throw ex;
} catch (NumberFormatException ex) {
// 예외 로그 출력
ex.printStackTrace();
// 예외 원인 조회 후 출력
ex.getCause().printStackTrace();
}
// checked exception 을 감싸서 unchecked exception 안에 넣습니다.
throw new RuntimeException(new Exception("이것이 진짜 예외 이유 입니다."));
}
}
결과 :
1) try 문 안에서 initCause 를 이용하여 원인 예외를 만들었다. (ex의 원인 예외 만듬)
그리고 그 예외를 던졌다.
2) catch 문에서 try 문에서 발생한 예외를 감지하고 로그를 출력한다.
(1) 아래 결과는 ex.printStackTrace() 만을 실행했을 때의 결과이다.
(결과 예외 -> 원인 예외 순으로 출력된다.)

(2) 다음 결과는 ex.getCause().printStackTrace(); 만을 실행했을 때의 결과
(원인 예외만 출력되는 것을 확인 할 수 있다.)

(3) 맨 아래줄에 무조건 실행되는 예외인 RuntimeException 을 실행 시에는 아래오 같은 결과가 나온다.
=> 이 경우는 checkedException 을 unchekcedException 으로 wrapping 하기 위한 코드이다.

throw new RuntimeException(new Exception("이것이 진짜 예외 이유 입니다."));
=> RuntimeException 으로 예외를 감쌈으로서 wrapping 하였다.
저거 없애면 컴파일시 예외 (checkedException)로 처리되어서 빨간 줄이 뜬다.

=> 이를 해결하기 위해서는 해당 메서드에 throws Exception 을 입력하여 메서드가 예외 가능성이 있다는 플래그를 주고, 컴파일 시에도 예외가 처리되도록 할 수 있다.



=> 로그가 살짝 다르게 나오긴 한다. (알아두면 좋을 듯)