학습 방식.
- 일단 떠오르는 걸 적기.
- 내용 중에서 핵심을 1문장씩 정리.(내용을 다 옮겨 적지 말것. 키워드 위주. 키워드만 표시 해도 무난. 세상엔 많은 블로그 자료가 있음.
- 오히려 밑줄 친것들 의문 들었던 것들을 집중 파헤치기.
아이템 1. 생성자 대신 정적 팩터리 메서드를 고려하라
- 생성자는 그 의미를 제대로 담아 내기 어려움
- 장점
- 따라서, 정적 팩터리 메서드는 나만의 이름으로 객체를 생성하는 규칙을 만들수 있는 장점(의미있는 메서드명). 그리고 반환타입도 다양하게 조치가 가능한 장점.
- 매번 인스턴스 생성할 필요 없
- 입력된 값에 따라 매번 다른 클래스
- 단점 이해 안되는 것
- 첫번째 상속을 하려면 퍼블릭, 프로택티드 생성자 필요하니, 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
- 테스트 해보니, 생성자는 선언 안하면 무조건 생성자 1개가 있고, 정적 팩터리만 제공하고, 해당 클래스를 익스탠드하는 클래스를 만들었는데 따로 컴파일 오류는 없는데, 이게 도대체 무슨 이야기인가.
- 프로그래머가 찾기 어렵다.
아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라
- 생성자에 매개변수가 4개이상이 되면, 빌더를 고려할것.
- 실제로 내 경험으로도 4개 넘어갔을때, 파라미터 위치를 헷갈려 이상한 값이 들어간적이 있음.
- 단순히 setter로 값을 세팅한다면 불변 클래스를 만들기 어렵다.
- lombok의 builder
- allArgsConstruct와 같이 사용하는 것은 피해야함.
- 모든 값 설정 가능.
- 따라서 생성자 레벨에서 “@Builder”를 쓰는것을 추천.
- build 매서드가 호출하는 생성자에서 불변식을 검사하자. 또한 생성자에서도 검사하자 라는 내용
- lombok의 기본 빌더는 이런 내용을 이해하지 못한다.
- 따라서 이런것들을 해결하기 위해서, 생성자에 빌더를 걸고, 생성자 내부에서 값을 해결하는 방식도 괜찮고, builder를 직접 만들고, 각 메서드마다 직접 검사하는 방식도 좋을듯.(중간단계에서도 유효성 체크가 가능해짐.)
- 주의
- 성능에 민감한 상황에서 문제 될수 있음
- 4개 이상일 때 바람직
아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라
- 가끔씩 내부 데이터를 보존하지 않는 객체는 싱글턴으로 하는 것이 메모리 측면에서 좋음.
- 딱하나만 만들어서 관리하자.
- 그 방법으로 프라이빗 생성자로 만들면 좋음.
- 방법
- 1 프라이븟 매서드
- 2 public static 메서드로
- 장점
- 마음이 바뀌면 싱글턴 아니게 변경 가능
- 이해안되는 장점 - >정적 패터리를 제네릭 싱글턴 팩터리로 만들수 있다. → 아이템 30까지 기다리자.
- 메서드 참조를 공급자로 가능.
- 3 enum 타입의 싱글턴
- 어색한 방법.
- 대부분의 상황에서 좋다고함.
- 그런데 이짓을 해본적이 살면서 없음.
아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라
- 이것도 이어진다. private 생성자를 만들면 외부에서 인스턴스화 할수 없기에 이 방법을 말한것.
- 상속을 막는 효과가 있다고 함.
아이템 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
- 이것은 전략 패턴과 이어지는 내용인듯.
- 그 자원이 그때 그때 변경 되는 것이라면, 그 자원들의 상위 타입을 내부에 변수로 넣고, 의존 객체 주입으로 관리하라는 의미인듯.
- 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다.
- 예시코드.
- 장점
- 단점
- 코드를 어지럽게 만듦.
- ← 의존 객체 프레임 워크를 사용하여 보완하자(Spring)
- 어떤 상황에서 이걸 써야할까?가 중요할듯.
아이템 6. 불필요한 객체 생성을 피하라
- 생서자 대신 팩터리 메서드를 씀으로써 불필요한 객체 생성을 피할수 있다.
- 유의사항
- String matches는 성능에 유의하여 사용
- 오토 박싱 주의
- 방어적 복사에 실패하면 언제 터질지 모르는 버그 ← 아이템 50. 확인해둘것.
하지만, 불필요한 객체 생성능 형태와 성능에만 영향
아이템 7. 다 쓴 객체 참조를 해제하라
- 다 쓴 객체 참조가 있을 것이다.
- 그 예로 스택을 이야기했던 것이 기억남.
- 스택과 같이 배열로 관리하면, 다쓴 객체인지 알길이 없음.
- 방법으로 수동으로 안쓰는 객체는 null로 치환해둘것.(ex 주소를 같는 배열의 값을 Null 로 설정)
- 자기 메모리를 직접관리하는 클래스는 메모리 누수에 주의하자.
운 좋게 캐시 외부에서 키(key)를참조하는 동안만(값이 아니다) 엔트리가 살아 있는 캐시가 필요한 상황이라면 WeakHashMap 을 사용해 캐시를 만들자. 다 쓴 엔트리는 그 즉시 자동으로 제거될 것이다. 단, WeakHashMap 은 이러한 상황에서만 유용하다는 사실을 기억하자
이펙티브 자바 Effective Java 3/E | 조슈아 블로크 저/개앞맵시(이복연) 역
[크레마 예스24 eBook]
http://m.yes24.com/Goods/Detail/90870798
- 누수의 3번째 주범 리스너랑 콜백
- 대처 : 콜백을 약한 참조(weekhashmap)로 저장하면 gc가 즉시 수거.
- 이해 못함.
https://blue-mina.tistory.com/4
- 참조에 대해
- 강한 : 일반적 방식. GC의 대상이 아님. Integer prime = 1;
- 부드러운 : SoftRefernce이용. 메모리부족 아니면 gc안함.
- 약한: WeekReference이용.
- WeakReference soft = new WeakReference(prime);
- prime이 널이면, GC
- WeekHashMap
- WeekReference의 특징이 사용됨.
- key에 해당하는 객체가 null이면 gc의 대상이 됨.(즉, key가 메모리에서 제거된다 라고 볼수 있을듯)
https://bepoz-study-diary.tistory.com/340
https://blog.breakingthat.com/2018/08/26/java-collection-map-weakhashmap/
https://medium.com/hackernoon/using-weahhashmap-to-save-references-to-callbacks-ed4f78ccb33
아이템 8. finalizer와 cleaner 사용을 피하라
- 써본적이 없어서 와닿지 않았다.
- 2가지 객체 소멸자.
- 예측할수 없고, 느리고, 불필요하다고함. gc에 의해 언제 소멸될지를 모름.
- 대안은?
- AutoClosable을 구현, 인스턴스 다쓰면 close 매서드를 호출할것.
아이템 9. try-finally보다는 try-with-resources를 사용하라
- 이거 쓰는것이 사용자의 실수를 막는 효과도 있고, 2중으로 try-catch를 하는 번거로움도 피하게 된다.
- 이거 쓰려면 AutoClosable을 구현 했어야함.
static String firstLineOfFile(String path, String defaultVal) {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return defaultVal;
}
}