이펙티브 자바 2장에서는 객체 생성, 불필요한 생성을 피하는 방법,
객체 파괴, 파괴전 필요한 작업들에 대해서 소개하고 있다.
아이템1. 생성자 대신 정적 패터리 메서드를 고려하라
- 정적 팩토리 메서드 장점
- 반환 객체의 특성을 고려하여 이름을 추가 가능
- 미리 만들어서 사용하거나 캐싱하는 등 붎필요한 객체 생성 회피
- 반환 타입의 하위 타입으로 반환 가능 (클라이언트는 인터페이스만 알도록 함)
- 입력한 매개변수에 따라 다른 클래스 객체 반환 가능
- 정적 팩토리 메서드를 작성은 반환 객체 클래스가 없어도 가능
- 정적 팩토리 메서드 단점
- 상속을 하려면
public또는protected생성자가 필요, 정적 팩토리 메서드만 제공하면 하위 클래스 생성 불가능 - 프로그래머가 찾기 어려움
- 상속을 하려면
- 명명 방식
from: 매개변수 하나 받아 해당 타입 인스턴스 반환of: 매개변수 여러개 받아 적합한 타입 인스턴스 반환valueOf:from과of보다 자세한 메서드instanceorgetInstance: 매개변수로 인스턴스를 반환하지만 동일한 인스턴스인지는 보장 안함createornewInstance:instance,getInstance동일, 하지만 매번 새로운 인스턴스 반환get{Type}:getInstance와 동일하지만, 생성 클래스가 아닌 다른 클래스에서 팩터리 메서드를 정의new{Type}:newInstance와 동일하지만, 생성 클래스가 아닌 다른 클래스에서 팩터리 메서드를 정의{type}:get{Type},new{Type}간결 버전
아이템2. 생성자에 매개변수가 밚다면 빌더를 고려하라
- 점층적 생성자 패턴 단점
- 매개변 수가 많아지면 작성, 읽기가 어려움
- 매개변수를 잘못 넣을 수도 있음
- 자바빈즈(
setter) 패턴 단점- 메서드 호출이 많아짐
- 불변으로 만들 수도 없음
- 완전한 객체 되기 전 일관성이 무너짐
- 스레드 안전하지 않음
- 빌더 패턴 장점
- 불변 가능
- 쓰거나 읽기 쉬움
- 선택적 매개변수
- 계층적으로 설계된 클래스와 함께 쓰기 좋음(추상 빌더)
아이템3. private 생성자나 열거 타입으로 싱글텀임을 보증하라
public static final방식private생성자로 하나뿐임을 보장- 코드가 간결
- 리플렉션 공격에 대비하기 위해
private생성자에 예외를 던져야 함
public static Object getInstance()방식- 언제든 싱글턴이 아니게 변경 가능
- 제네릭 팩터리 로 만들기 가능
- 메서드 참조를
supplier로 사용할 수 있음 - 위 장점들이 필요없다면
public static필드 방식 선호
- 열거(
enum) 타입 방식public static필드 방식보다 더 간결하고 쉽게 직렬화 가능- 리플렉션 공격에도 문제 없음
- 싱글턴을 이용하려면 원소가 하나뿐인 열거타입이 가장 적합
아이템4. 인스턴스화를 막으려거든 private 생성자를 사용하라
정적 멤버만 있는 유틸리티 클래스는 인스턴스화가 필요 없음
→ private 생성자를 추가하고 예외를 던져 클래스 내부에서도 인스턴스화 방지
아이템5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
클래스 내부에 있는 자원이 동작에 영향을 준다면 싱글턴, 유틸리티는 안됨
→ 생성자에 자원을 넘겨주어 (의존 객체 주입 패턴) 사용해야 함
→ 테스트 용이성, 유연성, 재사용성 개선
아이템6. 불필요한 객체 생성을 피하라
- String 생성자보다 문자열 리터럴 (
new String("test")→"test") - 생성자 보다는 정적 팩터리 메서드 사용
- 비싼 객체일 경우 캐싱해서 재사용
- 의도치 않은 오토 박싱이 되지 않도록 주의(박싱 타입보다는 기본 타입 사용)
- 무거운 객체가 아니라면 직접 만든 객체 풀(pool)은 코드가 복잡해지고 메모리 사용량도 늘어남(가비지 컬렉터가 훨씬 빠름)
아이템7. 다 쓴 객체 참조를 해제하라
- 다 쓴 변수는 유효 범위 밖으로 밀어내어 참조 해제
- 메모리를 직접관리하는
Stack클래스에서 참조를 다 썼다면null로 처리NullPointerException이 발생하겠지만 오류는 가능한 빨리 발견해야 함- 메모리 누수에 주의
- 키를 참조하는 동안만 객체가 살아있는 캐시가 필요하다면
WeakHashMap을 이용 - 리스너(listener), 콜백(callback)은 계속 쌓이지 않도록 약한 참조(weak reference) 로 저장
아이템8. finalizer 와 cleaner 사용을 피하라
try-with-resources 와 try-finally (AutoCloseable 구현) 사용하여 해결
finalizer 와 cleaner는 안전망 역할 또는 중요하지 않은 네이티브 자원 회수용으로만 사용
finalizer와cleaner문제점- 즉각 수행된다는 보장이 없음
- 동작중 발생된 예외를 무시, 작업이 남아있어도 즉시 종료
- 성능이 떨어짐
- 공격에 노출되어 보안 문제 (직렬화 도중 예외로 하위 클래스의 finalizer 수행 가능)
item9. try-finally보다는 try-with-resources를 사용하라
close메서드 호출 놓치기 쉬움- 코드가 간결하고 명확
- 예외 처리 유용
- 쉬운 자원 회수