체크 예외 전체 코드
package hello.jdbc.exception.basic;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
@Slf4j
public class CheckedTest {
@Test
void checked_catch() {
MyCheckedException.Service service = new MyCheckedException.Service();
service.callCatch();
}
@Test
void checked_throw() {
MyCheckedException.Service service = new MyCheckedException.Service();
Assertions.assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
/**
* Exception 을 상송받은 예외는 체크 예외가된다.
*/
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
/**
* Checked 예외는
* 예외를 잡아서 처리하거나 던지거나 선택해야한다.
*/
static class Service {
Repository repository = new Repository();
/**
* 예외를 잡아서 처리하는 코드
*/
public void callCatch() {
try {
repository.call();
} catch (MyCheckedException e) {
//예외처리 로직
log.info("예외처리, message={}", e.getMessage(), e);
}
}
/**
* 체크 예외를 밖으로 던지는 코드
* 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야한다.
*/
public void callThrow() throws MyCheckedException {
repository.call();
}
}
static class Repository {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
}
}
Exception을 상속받은 예외는 체크 예외가 된다.
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
먼저 예외를 잡아서 처리하는 코드를 실행해보자
@Test
void checked_catch() {
MyCheckedException.Service service = new MyCheckedException.Service();
service.callCatch();
}
service.callCatch() 에서 예외를 처리했기 때문에 테스트 메서드까지 예외가 올라오지 않는다.
실행 순서를 분석해보자.
1. test service.callCatch() repository.call() [예외 발생, 던짐]
2. test service.callCatch() [예외 처리] repository.call()
3. test [정상 흐름] service.callCatch() repository.call()
Repository.call() 에서 MyUncheckedException 예외가 발생하고, 그 예외를 Service.callCatch() 에서 잡는 것을 확인할 수 있다.
log.info("예외 처리, message={}", e.getMessage(), e);
실행 결과
[Test worker] INFO hello.jdbc.exception.basic.CheckedTest - 예외 처리, message=ex
hello.jdbc.exception.basic.CheckedTest$MyCheckedException: ex
at
hello.jdbc.exception.basic.CheckedTest$Repository.call(CheckedTest.java:64)
at
hello.jdbc.exception.basic.CheckedTest$Service.callCatch(CheckedTest.java:45)
at hello.jdbc.exception.basic.CheckedTest.checked_catch(CheckedTest.java:14)
체크 예외를 잡아서 처리하는 코드
try {
repository.call();
} catch (MyCheckedException e) {
//예외처리 로직
log.info("예외처리, message={}", e.getMessage(), e);
}
이번에는 예외를 처리하지 않고, 밖으로 던지는 코드를 살펴보자.
@Test
void checked_throw() {
MyCheckedException.Service service = new MyCheckedException.Service();
Assertions.assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
실행 순서를 분석해보자.
1. test service.callThrow() repository.call() [예외 발생, 던짐]
2. test service.callThrow() [예외 던짐] repository.call()
3. test [예외 도착] service.callThrow() repository.call()
체크 예외를 밖으로 던지는 코드
public void callThrow() throws MyCheckedException {
repository.call();
}
체크 예외의 장단점
체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외 를 필수로 선언해야 한다. 그렇지 않으면 컴파일 오류가 발생한다. 이것 때문에 장점과 단점이 동시에 존재한다.