이펙티브 자바/2장 객체 생성과 파괴 9

아이템 9 try-finally 보다는 try-with-resources를 사용하라

자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원들이 있다. try-with-resources를 쓰면 AutoCloseable 또는 Closeable 인터페이스를 구현한 자원 객체들을 사용 후, 자동으로 close 하게 할 수 있다. 예시 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class TryWithResourcesExample { public static void main(String[] args) { // 파일 경로 지정 String filePath = "example.txt"; // try-with-resources를 사용하여 BufferedReade..

아이템 8 finalizer와 cleaner 사용을 피하라

- 자바는 finalizer와 cleaner라는 두 가지 객체 소멸자를 제공한다. - finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. (deprecated) - cleaner는 그 대안으로 소개되었지만 여전히 예측할 수 없고 느리고 일반적으로 불필요하다. finalizer와 cleaner를 쓰지 않아야 할 구체적인 이유 finalizer와 cleaner는 즉시 수행된다는 보장이 없다. 그래서 제때 실행되어야 하는 작업은 절대 할 수 없다. 자바 언어 명세는 어떤 스레드가 finalizer를 수행할지 명시하지 않았으니, 이 문제를 예방할 보편적인 해법은 finalizer를 사용하지 않는 방법뿐이다. cleaner는 자신을 수행할 스레드를 제어할 수 있다는 면에서 조..

아이템 7 다 쓴 객체 참조를 해제하라

가비지 컬렉션 언어에서는 (의도치 않게 객체를 살려두는) 메모리 누수를 찾기가 아주 까다롭다. 객체 참조 하나를 살려두면 가비지 컬렉터는 그 객체뿐 아니라 그 객체가 참조하는 모든 객체(그리고 또 그 객체들이 참조하는 모든 객체)를 회수해가지 못한다. 그래서 잠재적으로 성능에 악영향을 줄 수 있다. 해법 null 처리(참조 해제)하면 된다. 하지만 모든 객체를 다 쓰자마자 일일이 null 처리하는 것은 프로그램을 필요 이상으로 지저분하게 만들 뿐이다. 객체 참조를 null 처리하는 일은 예외적인 경우여야 한다. 더 좋은 해법 참조를 담은 변수를 유효 범위(scope) 밖으로 밀어내는 것이다. 나머지 메모리 누수 주범 캐시, 리스너, 콜백 역시 메모리 누수를 일으키는 주범이다. WeakHashMap의 를 ..

아이템 6 불필요한 객체 생성을 피하라

- 불필요한 객체 생성을 피하자. new String("str") 반복 사용 지양 생성자 대신 팩터리 메서드 (ex: Boolean.valueOf(String)) String.matches 반복 사용 지양 박싱된 기본 타입보다는 기본 타입을 사용하고, 의도치 않은 오토박싱이 숨어들지 않도록 주의하자. 하지만, 요즘의 JVM에서는 별다른 일을 하지 않는 작은 객체를 생성하고 회수하는 일이 크게 부담되지 않는다. 프로그램의 명확성, 간결성, 기능을 위해서 객체를 추가로 생성하는 것이라면 일반적으로 좋은 일이다. 그래서 결론은, 중요성을 잘 판단해서 객체를 생성하고 재사용하자.

아이템 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

- 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. - 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이 적합하다. public class SpellChecker { private final Lexicon dictionary; private SpellChecker(Lexicon dictionary) { this.dictionary = Objects.requireNonNull(dictionary); } public boolean isValid(String word) { return true; } public List suggestions(String typo) { return null; } } - 생성자에 자원 팩터리를 넘겨주는 방식. Mos..

아이템 3 private 생성자나 열거 타입으로 싱글턴임을 보증하라

public static final 필드 방식의 싱글턴 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis(){...} public void leaveTheBuilding(){...} } - 장점 클래스가 싱글턴임이 API에 명백히 드러난다는 것 간결함 정적 팩터리 방식의 싱글턴 public class Elvis{ private static final Elvis INSTANCE = new Elvis(); private Elvis() {...} public static Elvis getInstance() {return INSTANCE; } public void leaveTheBuilding() {...} }..

아이템 2 생성자에 매개변수가 많다면 빌더를 고려하라

- 점층적 생성자 패턴도 쓸 수는 있지만, 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다. - 자바빈즈 패턴은 더 읽기 쉬운 코드지만 객체 하나를 만드는데 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성(consistency)이 무너진 상태에 놓이게 된다. - 이러한 단점을 완화하고자 생성이 끝난 객체를 수동으로 '얼리고(freezing)', 얼리기 전에는 사용할 수 없도록 하기도 한다. - 이런 상황에서 나온 대안이 빌더 패턴(Builder pattern)이다. 빌더의 생성자와 메서드에서 입력 매개변수를 검사하고, build 메서드가 호출하는 생성자에서 여러 매개변수에 걸친 불변식(invariant)을 검사하자. 생성 비용이 크지는 않지만 성능에 민감한 상황..

아이템 1 생성자 대신 정적 팩터리 메서드를 고려하라

이름을 가질 수 있다. 생성자에 넘기는 매개변수와 생성자 자체만으로는 반환될 객체의 특성을 제대로 설명하지 못한다. 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다. 반환할 객체의 클래스를 자유롭게 선택할 수 있게 하는 '엄청난 유연성'을 선물한다. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다. 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다. 메서드 이름을 통해 객체를 생성하고, 메서드 내부에서 실제로 어떤 클래스의 인스턴스를 생성할지를 결정할 수 있다. 따라서 정적 팩터리 메서드를 작성할 때에는 반환할 객체의 구체적인 클래스에 대한 결정을 미룰 수 있다. interface Shap..