[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 오류가 날것이다. 이를 위해 다시 객체들을 반복해서 탐색하는 것은 별다른 실익이 없다.
댓글남기기