■ 매개 변수가 유효한지 검사하라
메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바란다. 이런 제약은 반드시 문서화해야 하며 메서드 몸체가 시작되기전에 검사해야 한다. 안그러면 실행되다가 예외가 발생할 수 있고, 더 나쁜 경우는 잘못된 값을 반환할 수 있다.
public, protected 메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화 해야한다.
/**
* 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이 null인지 검사하는 코드가 없는데 그 이유는 이 설명을 BigInteger 클래스 수준에서 기술했기 때문이다.
자바 7에 추가된 java.uti.Objects.requireNonNull 메서드는 유연하고 사용하기 편하니, 더 이상 null 검사를 수동으로 하지 않아도 된다.
import java.util.Objects;
public class NullCheckTest {
public static void main(String[] args) {
String s = null;
Objects.requireNonNull(s, "s가 null 입니다.");
}
}
실행 결과
■ 단언문(Assert)
public이 아닌 메서드라면 단언문(assert)를 사용해 매개변수 유효성을 검증할 수 있다. 여기서의 핵심은 이 단언문들은 자신이 단언한 조건이 무조건 참이라고 선언한다는 것이다.
private 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;
//계산 수행 ...
}
일반적인 유효성 검사와 단언문이 다른 점
- 실패하면 AssertionError를 던진다.
- 런타임에 아무런 효과도, 아무런 성능 저하도 없다. (단, java를 실행할 때 명령줄에서 -ea 혹은 --enableassertions 플래그를 설정하면 런타임에 영향을 준다.)
■ 예외 상황
메서드 몸체 실행 전에 매개변수 유효성을 검사해야 한다는 규칙에도 예외는 있다. 유효성 검사 비용이 지나치게 높거나 실용적이지 않을 때, 혹은 계산 과정에서 암묵적으로 검사가 수행될 때 이다.
예를 들어 Collections.sort(List)처럼 객체 리스트를 정렬하는 메서드를 생각해보면 리스트 안의 객체들은 모두 상호 비교될 수 있어야 하며, 정렬 과정에서 이 비교가 이뤄집니다. 만약 상호 비교될 수 없는 타입의 객체가 들어있다면 그 객체와 비교할 때 ClassCastException을 던진다. 따라서 비교하기 앞서 리스트 안의 모든 객체가 상호 비교될 수 있는지 검사해봐야 별다른 이익이 없다.
■ 핵심 정리
- 메서드나 생성자 생성 시 매개변수들 제약 코드 시작 부분에 검사 및 문서화
'Effective Java' 카테고리의 다른 글
[Effective Java] 아이템51 메서드 시그니처를 신중히 설계하라 (0) | 2021.07.04 |
---|---|
[Effective Java] 아이템50 적시에 방어적 복사본을 만들라 (0) | 2021.07.04 |
[Effective Java] 아이템48 스트림 병렬화는 주의해서 적용하라 (0) | 2021.06.29 |
[Effective Java] 아이템47 반환 타입으로는 스트림보다 컬렉션이 낫다 (0) | 2021.06.29 |
[Effective Java] 아이템46 스트림에서는 부작용 없는 함수를 사용하라 (0) | 2021.06.28 |