[Effective Java] 아이템49 - 매개변수가 유효한지 검사하라

메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바란다. “오류는 가능한 한 빨리 잡아야 한다” 따라서 메서드 혹은 생성자로 인입되는 파라미터의 유효성을 검사하자

publicprotected 메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화해야 한다.

BigInteger.class 의 mod 메서드

    /**
     * Returns a BigInteger whose value is {@code (this mod m}).  This method
     * differs from {@code remainder} in that it always returns a
     * <i>non-negative</i> BigInteger.
     *
     * @param  m the modulus.
     * @return {@code this mod m}
     * @throws ArithmeticException {@code m} &le; 0
     * @see    #remainder
     */
    public BigInteger mod(BigInteger m) {
        if (m.signum <= 0)
            throw new ArithmeticException("BigInteger: modulus not positive");

        BigInteger result = this.remainder(m);
        return (result.signum >= 0 ? result : result.add(m));
    }

이 메서드는 m이 nulldlaus m.signum()을 호출할 때 NullPointerException을 던진다. 하지만 주석에 이러한 내용을 덧붙이지 않은 이유는 BigInteger 클래스 수준의 주석에 이미 명시를 했기 때문이다. (근데 이렇게 꼼꼼하게 볼까 싶다)

java.util.Objects.requireNonNull 메서드로 Null 검사를 유연하게 할 수 있다. 원하는 메시지도 넣을 수 있다.

this.strategy = Objects.requireNonNull(strategy, "전략");

공개되지 않은 메서드라면 assert 를 사용하자

private 이라면 메서드가 호출되는 상황을 통제할 수 있다. 아래와 같이 assert 문을 통해 매개변수 유효성을 검증할 수 있다.

public static void sort (long[] a, int offset, int length) {
    assert a != null;
    assert offset >= 0 && offset <= a.length;
    assert length >= 0 && length <= a.length - offset;
}

여기서 assert 문이 실패하면 AssertionError 를 던진다. 또한 런타임에 아무런 효과도 아무런 성능 저하도 없다.

메서드가 직접 사용하지는 않으나 나중에 쓰기 위해 저장하는 매개변수는 특히 신경쓰자

아이템20에서 int[] 를 List 로 반환해주는 (골격 구현을 통한) 구체 클래스를 다시 보자

매개변수로 받은 int[] aObjects.requireNonNull(a) 로 유효성을 검사한다. 만약에 여기서 검사를 안했다면 반환된 List 를 사용하려 할 때 비로소 NullPointerException이 발생한다

유효성 검사 비용이 지나치게 높거나 실용적이지 않다면 고려해보자

예를 들어 Collections.sort(List) 처럼 객체 리스트를 정렬하는 메서드가 있을 경우, 리스트 안의 모든 객체들은 모두 상호비교되어야 한다. 비교될 수 없는 타입의 객체가 끼어있다면 ClassCastException 오류가 날것이다. 이를 위해 다시 객체들을 반복해서 탐색하는 것은 별다른 실익이 없다.

댓글남기기