Item49. 매개변수가 유효한지 검사하라
매개변수 검사 시점
method와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바란다. 예컨대 인덱스 값은 음수이면 안되며, 객체 참조는 null이 아니어야 한다는 식이다.
이런 제약은 반드시 문서화해야 하며, method 몸체가 시작되기 전에 검사해야 한다.
method 몸체가 실행되기 전에 매개변수를 확인한다면, 잘못된 값이 넘어왔을때 즉각적이고 깔끔한 방식으로 예외를 던질 수 있다.
그렇지 않은 경우에는 다음과 같은 단점을 가질 수 있다.
- method가 수행되는 중간에 모호한 예외를 던지며 실패할 수 있다.
- 잘못된 결과가 나온다.
- 객체를 이상한 상태로 변경해서 , 해당 method에서는 정상적으로 수행되는 것 처럼 보이지만, 미래의 시점에서 해당 method와 관련없는 오류를 낸다.
매개변수 검사 관련 문서화
public 과 protected method는 매개변수 값이 잘못됬을 떄 던지는 예외를 문서화해야한다. (@throws javadoc 이용)
예를 들면 다음과 같다.
1 | /*** |
만약 개별 method에 적용되는 사항이 아니라 전체 public method에 적용된다면 class애 기입하면 된다.
위의 예에서도 매개변수가 null일떄, NullPointerException을 던진다는 설명은 class 수준에 기입되어 있다.
jdk 7부터 추가된 java.util.Objects.requireNonNull method는 null검사를 수동으로 하지 않게 해주며, 원할경우 예외 메시지도 두번쨰 매개변수로 넘겨줄 수 있다.
1 | this.strategy = Objects.requireNonNull(strategy,"전략"); |
assert 예약어
공개되지 않은 method라면 method가 호출되는 상황을 통제해야 한다. 오직 유효한 값만이 method에 넘어오는 것을 보증해야한다.
1 | private static void sort(long a[], int offset , int length){ |
위처럼 assert 를 사용해 매개변수 유효성을 검증할 수 있다.
assert에서는 표현식을 확인해 무조건 참이라고 선언하고 실패하면 AssertionError를 던진다.
runtime에 assert문을 활성화시키려면 java -ea , -enableassertions 로 실행해야한다.
(https://docs.oracle.com/javase/7/docs/technotes/guides/language/assert.html)
method가 직접 사용하진 않으나, 나중에 쓰기 위해 저장하는 매개변수는 특히 신경써서 검사해야 한다.
또한 생성자에서도 매개변수 유효성검사는 클래스 불변식을 어기는 객체가 만들어지지 않도록꼭 필요하다.
예외사항
- 유효성검사 비용이 지나치게 높은 경우, 실용적이지 않은 경우와 계산 과정에서 암묵적으로 검사가 수행될 때
예를 들어 Collections.sort(List)의 List내 모든 객체는 상호 비교될 수 있어야 하며, 그렇지 않을 경우에는 해당 객체와 비교할떄 classCastException을 던진다. 따라서 method호출이전에 유효성검증을 하더라도 실효성이 없다.
추가로 던지기로 한 예외와 API문서 예외가 다르다면 예외 번역 (exception translate)관용구를 사용하여 API에 기재된 문서로 번역해주어야 하는데 이 부분은 Item 73에서 다룬다.