[Effective Java] 아이템49 - 매개변수가 유효한지 검사하라
메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바란다. “오류는 가능한 한 빨리 잡아야 한다” 따라서 메서드 혹은 생성자로 인입되는 파라미터의 유효성을 검사하자
public
과 protected
메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화해야 한다.
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} ≤ 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[] a
를 Objects.requireNonNull(a)
로 유효성을 검사한다. 만약에 여기서 검사를 안했다면 반환된 List
를 사용하려 할 때 비로소 NullPointerException
이 발생한다
유효성 검사 비용이 지나치게 높거나 실용적이지 않다면 고려해보자
예를 들어 Collections.sort(List)
처럼 객체 리스트를 정렬하는 메서드가 있을 경우, 리스트 안의 모든 객체들은 모두 상호비교되어야 한다. 비교될 수 없는 타입의 객체가 끼어있다면 ClassCastException
오류가 날것이다. 이를 위해 다시 객체들을 반복해서 탐색하는 것은 별다른 실익이 없다.
댓글남기기