Effective Java 3E
학습기록 - 불필요한 객체 생성을 피하라
똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 특히 불변 객체는 언제든 재사용할 수 있다. 다음 코드는 하지 말아야 할 극단적인 예이니 주의하자! String s = new String("bikini"); 위 문장을 실행이 될 때 마다 String 인스턴스를 새로 만든다. 이는 불필요한 행위이다. 이 문장이 반복문이나 빈번하게 호출되는 메서드 안에 있다면 쓸데없는 String 인스턴스가 수백만 개 만들어져 메모리 공간을 차지할 수 있다. 그러면 어떻게 써야 더 나은 방식일까? 다음 코드는 위 코드의 개선된 방식이다. 우리가 자주 보던 방식이어서 익숙할 수 있다. String s = "bikini"; 이 코드는 새로운 인스턴스를 매번 만드는 대신 하나의 String..
학습기록 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
많은 클래스가 하나 이상의 자원에 의존한다. 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. 대신 클래스가 여러 자원 인스턴스를 지원해야 하며, 클라이언트가 원하는 자원을 사용해야 한다. 이 조건을 만족하는 간단한 패턴으로는 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다. 아래의 코드가 그 예시이다. public class SpellChecker{ private final Lexicon dictionary; public SpellChecker(Lexicon dictionary){ this.dictionary = Objects.requireNonNull(dictionary); } public boolean isValid(String wo..
학습기록 - 인스턴스화를 막으려거든 private 생성자를 사용하라
가끔 단순히 정적 메서드와 정적 필드만을 담은 클래스를 만들고 싶을 때가 있을 것이다. 객체 지향적 면에서 보면 곱지는 않지만, java.lang.Math와 java.util.Arrays처럼 기본 타입 값이나 배열 관련 메서드들을 모아 놓을 수 있는 클래스이다. 또한, java.util.Collections처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드(혹은 팩토리)를 모아놓을 수도 있다. (자바8부터는 이런 메서드들을 인터페이스에 넣을 수 있다.) 마지막으로, final 클래스와 관련한 메서드들을 모아놓을 때도 사용한다. 정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한 게 아니지만, 생성자를 명시하지 않으면 컴파일러가 자동으로 기본 생성자를 만들어준다. 즉, 매개변수를..
학습기록 - private 생성자나 열거 타입으로 싱글턴임을 보증하라
싱글턴(singleton)이란? - 인스턴스를 오직 하나만 생성할 수 있는 클래스를 의미 싱글턴의 전형적인 예) 함수와 같은 무상태(stateless) 객체나 설계상 유일해야 하는 시스템 컴포넌트 등 But 클래스를 싱글턴으로 만들면 이를 사용하는 클라이언트는 테스트하기가 어려워질 수 있다. → 타입을 인터페이스로 정의한 다음 그 인터페이스를 구현해서 만든 싱글턴이 아니라면 싱글턴 인스턴스를 가짜(mock) 구현으로 대체할 수 없기 때문. 싱글턴을 만드는 방식은 보통 둘 중 하나다. 두 방식 모두 생성자는 private으로 감춰두고, 유일한 인스턴스에 접근할 수 있는 수단으로 public static 멤버를 하나 마련해준다. public class Singleton { public static final..
학습기록 - 생성자에 매개변수가 많다면 빌더를 고려하라
정적 팩토리와 생성자에는 똑같은 제약이 하나 있다. 선택적 매개변수가 많을 때 적절히 대응하기 어렵다는 점이다. 예를 들어 식품 포장의 영양정보를 표현하는 클래스를 보자. 영양 정보는 1회 내용량, 총 n회 제공량, 1회 제공량당 칼로리 같은 필수 항목 몇 개와 총 지방, 트랜스지방, 포화지방, 콜레스테롤, 나트륨 등 총 20개가 넘는 선택항목으로 이뤄진다. 그런데 대부분 제품은 이 선택 항목 중 대다수의 값이 그냥 0이다. 이럴때 프로그래머들은 점층적 생성자 패턴(telescoping constructor pattern)을 즐겨 사용한다. 다음의 코드는 책의 점층적 생성자 패턴의 예시 코드이다. public class NutritionFacts{ private final int servingSize; ..
학습기록 - 생성자 대신 정적 팩토리 메서드를 고려하라
정적 팩토리 메서드(Static Factory Method)는 객체 생성을 위한 디자인 패턴 중 하나이다. 일반적으로 객체를 생성하는 방법은 생성자를 이용하는 것인데, 정적 팩토리 메서드는 생성자와 다르게 메서드를 이용하여 객체를 생성한다. 생성자 vs 정적 팩토리 메서드 일반적으로 생성자는 호출하는 쪽에서 인스턴스의 타입을 명시해주어야 하지만, 정적 팩토리 메서드는 메서드명에 따라 타입이 결정되기 때문에 호출하는 쪽에서는 타입을 명시할 필요가 없다. 또한, 이러한 메서드를 이용하면 생성되는 객체가 항상 새로운 객체가 아닐 수 있으며, 이전에 생성된 객체를 반환할 수도 있다. BigInteger(int, int, Random){ ... // 생성자 코드 } BigInteger.probablePrime{ ..