반응형

1. 개요

 비지니스 코드를 재사용 하는 것이 좋은 것처럼, 예외도 재사용 하는 것이 좋다. 자바 라이브러리는 대부분 API에서 쓰기 충분한 수의 예외를 제공한다. 커스텀 예외를 사용해도 되지만 표준 예외를 사용했을 때 사용자 입장에서 익숙한 예외가 발생하므로 예외 상황 파악과 코드 이해가 쉬워진다.

 

 재사용할만한 표준 예외들을 알아보자.

 

2. 재사용할만한 예외

 

IllegalArgumentException

 호출자가 인수로 부적절한 값을 넘길 때 던지는 예외이다. 예를 들어 반복 횟수를 지정하는 매개변수에 음수를 건넬 때 쓸 수 있다.

 

public class Call {

    private static final String HI = "hello";

    public void sayHi(int cnt){

        if(cnt < 0){
            throw new IllegalArgumentException("cnt 값은 0보다 커야 합니다.");
        }

        for(int i =0; i<cnt; i++){
            System.out.println(HI);
        }
    }
}

 

 

IllegalArgumentException

 

IllegalStateException

 대상 객체의 상태가 호출된 메서드를 수행하기에 적합하지 않을 때 주로 던진다. 예를 들어 제대로 초기화되지 않은 객체를 사용하려 할 때 던질 수 있다.

 

public class Toy {

    private String weapon;

    public Toy(String weapon){
        this.weapon = weapon;
    }

    public void attack(){
        if(weapon == null){
            throw new IllegalStateException("weapon 값이 초기화되지 않았습니다. 초기화시켜주세요.");
        }

        System.out.println(weapon +" 공격!");
    }
}

 

IllegalStateException

 

NullPointerException

 일반적으로 null 값을 갖고 있는 객체나 변수를 호출할 때 발생하지만, 특정 상황에선 이를 재사용할 수 있다. null 값을 허용하지 않는 메서드에 null을 건네면 관례상 IllegalArgumentException이 아닌 NullPointerException을 던진다.

 아래와 같이 attack() 메서드를 실행하기 전, 생성자 메서드 레벨에서 NullPointerException을 사용하는 방법이다. 인스턴스 생성 시점에 멤버필드에 대한 유효성이 보장된다는 점에서 더 좋은 방법이라 생각한다.

 

public class Toy {

    private String weapon;

    public Toy(String weapon){
        if(weapon == null){
            throw new NullPointerException("weapon 을 null 로 설정할 수 없습니다.");
        }
        this.weapon = weapon;
    }

    public void attack(){
        System.out.println(weapon +" 공격!");
    }
}

NullPointerException

 

UnsupportedOperationException

 클라이언트가 요청한 동작을 대상 객체가 지원하지 않을 때 던진다. 보통 구현하려는 인터페이스의 메서드 일부를 구현할 수 없을 때 쓰는데, 예를 들어 원소를 넣을 수만 있는 List 구현체에 누군가 remove 메서드를 호출하면 이 예외를 던질 것이다.

 

public class NoRemoveList<E> extends ArrayList<E> {

    @Override
    public boolean remove(Object o) {
        throw new UnsupportedOperationException("remove는 지원하지 않습니다.");
    }
}

 

UnsupportedOperationException

 

이 외에도 어떤 시퀀스의 허용 범위를 넘을 때 사용하는 IndexOutOfBoundException, 단일 스레드에서 사용하려고 설계한 객체를 여러 스레드가 동시에 수정하려 할 때 사용하는 ConcurrentModificationException 등이 있다.

 

3. 재사용하지 말아야할 예외

 Exception, RuntimeException, Throwable, Error는 재사용하지 말자. 이 예외들은 다른 예외들의 상위 클래스이기 때문에 예외 상황에 대한 정보를 명확하게 전달하기 어렵다.

 

4. 정리

 상황에 부합한다면 항상 표준 예외를 재사용하자. 단, 표준 예외를 사용하기 전 API 문서를 참고해 그 예외가 어떤 상황에서 던져지는지 꼭 확인해야 한다. 예외의 이름 뿐 아니라 예외가 던져지는 맥락도 부합할 때만 재사용한다. 더 많은 정보를 제공하길 원한다면 표준 예외를 확장해도 좋다.

 

반응형

+ Recent posts