자바

예외

연향동큰손 2025. 2. 2. 15:11

 

Error ==> 메모리 부족이나 심각한 시스템 오류와 같이 애플리케이션에서 복구 불가능한 시스템 예외이다.

개발자는 이 예외를 catch나 Throwable로 잡으려고 해서는 안된다.

 

체크 예외(Exception), 언체크 예외(RuntimeException)

 

Exception

  • Exception = 컴파일러가 체크하는 체크 예외이며, 애플리케이션 로직에서 사용할 수 있는 실질적인 최상위 예외이다.
  • 하위 예외로 SQLExceptoin과 IOException이 있다.

RuntimeException

  • 컴파일러가  체크하지 않는 언체크 예외이다.
  • 하위 언체크 예외로 NullPointException과 IllegalArgumentException이 있다.

 

 

예외 기본 규칙

 

 

 

 

 

예외는 잡아서 처리하거나 처리를 못하면 밖으로 던지도록 되어있다.

 

 

예외 기본 원칙

  1. 예외는 잡아서 처리하거나 던져야 한다.
  2. 예외를 던질 때 지정한 예외뿐만 아니라 그 예외의 자식들도 함께 처리된다.

 

체크 예외

 

체크예외의 경우 개발자가 예외를 누락해도 컴파일러를 통해 문제를 잡을 수 있어 훌륭한 안전 장치이다.

 

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() {
        Service service = new Service();
        service.callCatch();
    }

    @Test
    void checked_throw() {
        Service service = new Service();
        Assertions.assertThatThrownBy(()->service.callThrow()).isInstanceOf(MyCheckedException.class);
    }

    // Exception을 상속받은 예외는 체크 예외가 된다.
    static class MyCheckedException extends Exception{
        public MyCheckedException(String message){
            super(message);
        }
    }

    static class Service{
        Repository repository = new Repository();

        public void callCatch(){
            try {
                repository.call();
            }catch (MyCheckedException e){
                log.info("예외 처리, message={}",e.getMessage(),e);
            }
        }

        public void callThrow() throws MyCheckedException{
            repository.call();
        }

    }

    static class Repository{
        public void call() throws MyCheckedException {
            throw new MyCheckedException("ex");
        }
    }
}

 

위 코드는 리포지토리에서 예외가 발생한 경우를 가정한 테스트이다.

 

서비스 계층의 callCatch()메서드를 보면 리포지토리의 예외를 캐치해 줬기 때문에 checked_catch()테스트에서 컴파일 오류가 발생하지 않고 테스트가 정상적으로 수행되었다.

 

하지만 callThrow는 예외를 처리하지 않고 밖으로 던져버리기 때문에 service.callThrow()를 하면 컴파일 오류가 발생한다.

 

 

언체크 예외

 

언체크 예외는 체크 예외와 다르게 컴파일러가 예외를 체크하지 않는다.

 

그리고 throws를 선언하지 않고 생략하여도 예외 발생시 자동으로 예외를 던진다.

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 UncheckedTest {

    @Test
    void unchecked_catch(){
        Service service = new Service();
        service.callCatch();
    }

    @Test
    void unchecked_throw(){
        Service service = new Service();
        Assertions.assertThatThrownBy(()-> service.callThrow()).isInstanceOf(MyUncheckedException.class);
    }

    static class MyUncheckedException extends  RuntimeException{
        public MyUncheckedException(String message){
            super(message);
        }
    }

    //Unchecked 예외는 예외를 잡거나, 던지지 않아도 된다. 예외를 잡지 않으면 자동으로 밖으로 던진다.
    static class Service{
        Repository repository = new Repository();

        public void callCatch(){
            try {
                repository.call();
            }catch (MyUncheckedException e){
                log.info("예외 처리, message={}",e.getMessage(),e);
            }
        }
        /**
         예외를 잡지 않아도 된다. 자연스럽게 상위로 넘어간다.
         체크 예외와 다르게 throws 예외 선언을 하지 않아도 된다.
         throws를 해줘도 상관없다.
         */
        public void callThrow(){
            repository.call();
        }
    }

    static class Repository{
        public void call(){
            throw new MyUncheckedException("ex");
        }
    }
}

 

위 코드를 보면 체크예외와 다르게 callThrow()에서 예외를 던져주지 않아도 예외가 발생하면 자동으로 던져준다.

따라서 throws를 생략 가능하다.

'자바' 카테고리의 다른 글

동시성 문제를 해결하기 위한 ThreadLocal[java]  (0) 2025.03.05
Thread란 무엇인가[Java]  (1) 2025.03.02
HashMap  (0) 2024.02.21
Iterator  (2) 2024.02.21
인터페이스로 객체 만들기  (0) 2024.02.20