본문 바로가기

분류 전체보기

(214)
[아이템 58] 전통적인 for 문보다는 for-each 문을 사용하라 [Why] 스트림이 제격인 작업이 있고 반복이 제격인 작업이 있다. for (Iterator i = c.iterator(); i.hasNext();) { Element e = i.next(); ... // e로 무언가를 한다. } for (int i=0; i
[아이템 57] 지역변수의 범위를 최소화하라 [Why] 지역변수의 유효 범위를 최소로 줄이면 코드 가독성과 유지보수성이 높아지고 오류 가능성은 낮아진다. [How] 1. 지역변수의 범위를 줄이는 가장 강력한 기법은 역시 '가장 처음 쓰일 때 선언하기'다. 사용하려면 멀었는데, 미리 선언부터 해두면 코드가 어수선해져 가독성이 떨어진다. 변수를 실제로 사용하는 시점엔 타입과 초깃값이 기억나지 않을 수도 있다. 2. 거의 모든 지역변수는 선언과 동시에 초기화해야 한다. 초기화에 필요한 정보가 충분하지 않다면 충분해질 때까지 선언을 미뤄야 한다. try-catch문은 이 규칙에서 예외다. 변수를 초기화하는 표현식에서 검사 예외를 던질 가능성이 있다면 try 블록 안에서 초기화해야 한다. (그렇지 않으면 예외가 블록을 넘어 메서드에까지 전파된다) 변수 값을..
[아이템 55] 옵셔널 반환은 신중히 하라 [배경] 자바 8 전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 취할 수 있는 선택지가 두 가지였다. 첫 번째는, 예외를 던지는 것이었다. 하지만 예외는 진짜 예외적인 상황에서만 사용해야 한다.(아이템69) 또한 예외를 생성할 때 스택 추적 전체를 캡처하므로 비용도 만만치 않다. 두 번째는, null을 반환하는 것이었다. 하지만 null을 반환할 수 있는 메서드를 호출할 때는 별도의 null 처리 코드를 추가해야 한다. 자바 8로 올라가면서 또 하나의 선택지가 생겼다. 그 주인공인 Optional는 null이 아닌 T 타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다. 아무것도 담지 않은 옵셔널은 '비었다'고 말한다. 반대로 어떤 값을 담은 옵셔널은 '비지 않았다'고 한다. 옵셔널은 ..
[아이템 54] null이 아닌, 빈 컬렉션이나 배열을 반환하라 [Why] private final List cheesesInStock = ...; /** * @return 매장 안의 모든 치즈 목록을 반환한다. * 단, 재고가 하나도 없다면 null을 반환한다. */ public List getCheeses() { return cheesesInStock.isEmpty() ? null : new ArrayList(cheesesInStock); } List cheeses = shop.getCheeses(); if (cheeses != null && cheeses.contains(Cheese.STILTON)) { System.out.println("좋았어, 바로 그거야."); } 컬렉션이나 배열 같은 컨테이너가 비었을 때 null을 반환하는 메서드를 사용할 때면 항상 방..
[아이템 53] 가변인수는 신중히 사용하라 ※ 가변인수(varargs) 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다. 가변인수 메서드를 호출하면, 먼저 인수의 개수와 길이가 같은 배열을 만들고 인수들을 이 배열에 저장하여 가변인수 메서드에 건네준다. 인수 개수는 런타임에 (자동 생성된) 배열의 길이로 알 수 있다. ※ printf는 가변인수와 한 묶음으로 자바에 도입되었고, 이때 핵심 리플렉션 기능(아이템65)도 재정비되었다. printf와 리플렉션 모두 가변인수 덕을 톡톡히 보고 있다. [Why] 인수가 1개 이상이어야 할 때도 있다. static int min(int... args) { if (args.length == 0) { throw new IllegalArgumentException("인수가 1개 이상 필요합니다."); } ..
[아이템 52] 다중정의는 신중히 사용하라 [Why] public class CollectionClassifier { public static String classify(Set s) { return "집합"; } public static String classify(List lst) { return "리스트"; } public static String classify(Collection c) { return "그 외"; } public static void main(String[] args) { Collections[] collections = { new HashSet(), new ArrayList(), new HashMap().values() }; for (Collection c : collections) { System.out.println..
[아이템 51] 메서드 시그니처를 신중히 설계하라 ※ API 설계 요령을 설명한다. 1. 메서드 이름을 신중히 짓자. 항상 표준 명명 규칙(아이템68)을 따라야 한다. 이해할 수 있고, 같은 패키지에 속한 다른 이름들과 일관되게 짓는 게 최우선 목표다. 그 다음 목표는 개발자 커뮤니티에서 널리 받아들여지는 이름을 사용하는 것이다. 긴 이름은 피하자. 애매하면 자바 라이브러리의 API 가이드를 참조하자. 2. 편의 메서드를 너무 많이 만들지 말자. 메서드가 너무 많은 클래스는 익히고, 사용하고, 문서화하고, 테스트하고, 유지보수하기 어렵다. (인터페이스도 마찬가지) 3. 매개변수 목록은 짧게 유지하자. 4개 이하가 좋다. 같은 타입의 매개변수 여러 개가 연달아 나오는 경우가 특히 해롭다. 순서를 기억하기 어려울뿐더러, 실수로 순서를 바꿔 입력해도 그대로 ..
[아이템 50] 적시에 방어적 복사본을 만들라 [Why] 자바는 안전한 언어다. 하지만 아무리 자바라 해도 다른 클래스로부터의 침범을 아무런 노력 없이 다 막을 수 있는 건 아니다. 그러니 클라이언트가 여러분의 불변식을 깨뜨리려 혈안이 되어 있다고 가정하고 방어적으로 프로그래밍해야 한다. public final class Period { private final Date start; private final Date end; /** * @param start 시작 시각 * @param end 종료 시각; 시작 시각보다 뒤여야 한다. * @throws IllegalArgumentException 시작 시각이 종료 시각보다 늦을 때 발생한다. * @throws NullPointerException start나 end가 null이면 발생한다. */ pub..