메서드에서 받는 매개변수에 대한 제약은 문서화해야 하며 몸체가 시작되기 전에 검사
매개변수 검사를 제대로 못했을 때 문제
java.util.Objects.requireNonNull 메서드를 사용하면 null 검사를 수동으로 하지 않아도 된다
this.strategy = Objects.requireNonNull(strategy, "전략");
공개되지 않은 메서드라면 패키지 제작자가 메서드가 호출되는 상황을 통제할 수 있어서 오직 유효한 값이 메서드에 넘겨지는 것을 보증할 수 있다
유효성 검사의 비용이 너무 높거나 암묵적으로 검사가 수행될때는 예외적으로 메서드 몸체 실행 전에 매개변수 유효성 검사를 해야된다는 원칙에서 예외이다
자바는 안전한 언어이지만 클라이언트가 이 안정성을 깨뜨리는것을 고려해서 방어적으로 프로그래밍 해야 한다
외부 공격으로부터 내부를 보호하려면 생성자에서 받은 가변 매개변수 각각을 방어적으로 복사하고 원본이 아닌 복사본을 이용하는 것도 고려해야 한다
매개변수가 제3자에 의해 확장될 수 있는 타입이라면 방어적 복사본을 만들 때 clone을 사용해서는 안된다
변경될 수 있는 객체가 클래스에 남겨진 뒤 임의로 변경되어도 그 클래스가 문제 없이 동작할지를 따저본 후 확신할 수 없다면 복사본을 만들어 저장해야 한다
방어적 복사를 사용하지 않을 케이스
재정의 메서드는 동적으로 선택되고 다중정의한 메서드는 정적으로 선택된다
메서드를 재정의했다면 해당 객체의 런타임 타입이 어떤 메서드를 호출할지의 기준이 된다
안전하고 보수적으로 가려면 매개변수 수가 같은 다중정의는 만들지 않는 것이 좋다
다중정의하는 대신 메서드 이름을 다르게 지어주는 것도 고려해야 한다
메서드를 다중정의할 때, 서로 다른 함수형 인터페이스라도 같은 위치의 인수로 받아서는 안된다
가변인수 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다
static int sum(int... args){
int sum = 0;
for (int arg : args)
sum += arg;
return sum;
}
메서드를 정의할 때 필수 매개변수는 가변인수 앞에 두어야 오류 방지할 수 있다
static int min(int firstArg, int... remainingArgs){
int min = firstArg;
for (int arg: reaminingArgs)
if (arg < min)
min = arg;
return min;
}
가변인수가 성능에 걸림돌이 될 수 있으니 성능에 민감한 상황일 때는 사용에 주의해야 한다
빈 컬랙션을 반환하는 쪽이 오류 방지에도 좋고, 빈 불변 객체를 생성하고 이를 반환하면 성능에도 영향을 주지 않는다
옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말아야 한다
옵셔널 활용
String lastWordInLexicon = max(words).orElse("단어 없음");
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
Element lastNobleGas = max(Elements.NOBLE_GASES).get();
여전히 적합한 메서드를 찾지 못했다면 isPresent로 옵셔널이 채워져 있으면 true, 비어 있으면 false를 반환
컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안된다
옵셔널을 맵의 값으로는 왠만한 경우에서는 사용하면 안된다
API를 올바로 문서화하려면 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야 한다
메서드용 문서화 주석에는 해당 메서드와 클라이언트 사이의 규약을 명료하게 기술해야 한다
전제조건과 사후조건뿐만 아니라 부작용도 문서화해야 한다
열거 타입을 문서화할 때는 상수들에도 주석을 달아야 한다
애너테이션 타입을 문서화할 때는 맴버들에도 모두 주석을 달아야 한다
클래스 혹은 정적 메서드가 스레드 안전하든 그렇지 않든, 스레드 안전 수준을 반드시 API 설명에 포함해야 한다