아이템15. 클래스와 멤버의 접근 권한을 최소화하라 어설프게 설계된 컴포넌트와 잘 설계된 컴포넌트의 가장 큰 차이는 뭘까? 바로 클래스 내부 데이터와 내 부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼느냐이다. 정보 은닉의 장점은 무엇이 있을까 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬적으로 개발할 수 있기 때문이다. 시스템 관리 비용을 낮춘다. 각 컴포넌트를 더 빨리 파악하여 디버깅 할 수 있기 때문이다. 다른 컴포넌트로 교체하는 부담도 적기 때문이다. 소프트웨어 재사용성을 높인다. 외부에 거의 의존하지 않고 독자적으로 동작할 수 있는 컴포넌트라면 그 컴포넌트와 함께 개발되지 않은 낯선 환경에서도 유용하게 쓰일 가능성이 크기 때문이다. 큰 시스템을 제작하는 난이도를 낮춰준다. 시스템 전체가 ..
아이템9. try-finally보다는 try-with-resources를사용하라 자바 라이브러리에서는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다. InputStream, OutputStream, java.sql.Connection 등이 좋은 예다. 하지만 자원 닫기(close)는 클라이언트가 놓치기 쉬워 예측할 수 없는 성능 문제로 이어지는 경우가 많다. 그런 자원 중 상당수가 안전망으로 finalizer를 사용하곤 있지만 finalizer는 그리 믿을만하지 못하다. 전통적인 자원 회수 방식 : try-finally 보통 자원이 제대로 닫히는 것을 보장하는 수단으로 사용됨. 예외가 발생하거나 메서드에서 반환되는 경우를 포함하는 수단으로 try-finally가 쓰였다. try-finally..
아이템7. 다 쓴 객체 참조를 해제하라. 자바는 C, C++처럼 메모리를 직접 관리하는 언어와 다르게 GC에 의해 메모리를 관리한다. GC가 메모리 관리를 해주지만, 메모리 관리에 신경 써야한다. 스택을 간단히 구현한 예제 코드를 살펴보자 Stack을 간단히 구현한 코드 public class Stack { private Object[] elements; private int size; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[..
아이템6. 불필요한 객체 생성을 피하라 불필요한 객체 생성 : new String() 사용 String name = new String("LHS"); // 매번 인스턴스를 생성 String name2 = new String("LHS"); // 같은 문자열이지만, 위 name과 참조하는 주소가 다르다 name, name2 둘 다 "LHS"라는 문자열을 가지게 된다. 하지만 new String()을 이용하여 만든 name, name2는 같은 "LHS"이지만, 두 문자열이 참조하는 주소는 모두 다르기 때문에 동일한 데이터에 대해 서로 다른 메로리를 할당한다는 낭비가 발생한다. String name3 = "LHS"; // 상수 Pool을 사용 String name4 = "LHS"; // 상수 Pool을 사용 그..
아이템5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원이 클래스 동작에 영향을 주는 경우가 있다. 아래의 SpellChecker 클래스는 사전(Dictionary)에 의존하고 있는데 아래처럼 구현하는 경우를 많이 볼 수 있다. 정적 유틸리티 사용 public class SpellChecker { private static final Lexicon dictionary = new LexiconDictionary(); private SpellChecker() { // 객체 생성 방지 } private static boolean isValid(String word) {...} // dictionary를 사용한 로직 public static L..
아이템4. 인스턴스화를 막으려거든 private 생성자를 사용하라 가끔 단순히 정적 메서드와 정적 필드만을 담은 클래스를 사용하면 유용할 때가 있다. 대표적으로 java.lang.Math, java.util.Arrays 와 같이 기본 타입 값이나 배열에 관련된 메서드들을 모아 놓는 유틸리티 클래스들을 사용할 수 있다. 또한 java.util.Collections 와 같이 특정 인터페이스를 구현하는 객체를 생성해 주는 정적 팩터리 메서드를 모아 놓을 수도 있다. 이러한 유틸리티 클래스들은 따로 인스턴스 변수나 메서드가 없어도 사용할 수 있으므로 생성자가 필요하지 않다. 하지만 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어 준다. 즉, 매개변수를 받지 않는 public 생성자가 만들어지며..
아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 싱글톤 이란? 싱글톤이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다. 싱글톤의 전형적인 예로는 무상태 객체나 유일한 시스템 컴포넌트를 들 수 있다. 하지만 싱글톤 클래스는 타입을 인터페이스로 정의하고 그것의 구현체로 정의한 것이 아니라면 테스트하기 어렵다는 문제가 있다. 싱글톤을 만드는 방법 1. public static 멤버가 final 필드인 방식 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Evlis () { } public void sining () { System.out.println("lalala"); } } priva..
아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라 빌더 패턴이란? 빌더 패턴은 선택적 매개변수가 많은 상황에서 생성자 혹은 정적 팩토리 메서드보다 더 유용하게 사용할 수 있다. 필더 패턴을 이해하기 위해 예시로 가상의 가방(Bag) 객체를 만들 것이다. 가방을 주문하여 만들 때, 가방의 크기는 필수로 입력해야 하지만, 나머지 옵션들은 주문하는 사람이 마음대로 결정할 수 있다고 가정하자. 여기서 필수 매개변수는 가방의 사이즈가 될 것이고, 여러 옵션들은 매개변수가 될 것이다. 빌더 패턴 사용 전 빌더 패턴을 사용하기 전에는, 많은 선택적 매개변수를 처리하기 위해 아래 두 가지 패턴이 사용 된다. 1) 점층적 생성자 패턴 (Telescoping Constructor Pattern) 점층적 생성자 패턴은 ..