보통은 scope를 이용하여 유효범위 밖으로 가면 GC가 알아서 제거되니까 신경안써도된다.
아이템 8. finalizer와 cleaner 사용을 피하라
두가지 객체 소멸자 finalizer와 cleaner
둘다 즉시 수행되지않는다. 언제실행될지는 GC만알수잇다.
내 JVM에서는 잘되도 남의 JVM에서의 순서는 바껴서 안될수도
아이템 9. try-finally보다는 try-with-resoure
자바 라이브러리에는 close메서드를 호출해 직접닫아줘야하는 자원이 많다
자원을 제대로 닫히는것을 보장하기위해 try-finally많이사용된다 하지만 자원이 두개이상이면 try-finally문 2번사용 복잡
try-with-resoure를 활용해야하며, AutoCloseable이 구현되어있는것이여야한다. 대부분의 클래스 라이브러리가 이미구현함.
매우 간결해지고, close()호출직접안해도됨
3장 모든 객체의 공통 메서드
Object 는 모든 클래스의 조상이며, final이 아닌 Object메서드들의 재정의는 약속하에 해야한다.
Comparable.compareTo도 이와비슷하다.
아이템 10. equals는 일반 규약을 지켜 재정의하라
equals의 재정의는 객체 식별성이 아닌 논리적 동치성을 비교가 필요할때다. 주로 값 클래스!(Integer, String)
즉, 객체가 같은지가 아니라 값이 같은지 물어볼때 (값 클래스라고 해도, 값이 같은 인스턴스가 둘 이상만들어지지않을때는 재정의필요없다.어차피 틀림)
== 연산자를 사용해 입력이 자기자신의 참조인지확인
instanceof 연산자로 입력이 올바른 타입인지 확인
입력을 올바른 타입으로 형변환한다.(위에과정에서검사완료)
입력 객체와 자기 자신의대응되는 핵심필드가 모두 일치시 true
equals()를 구현했다면 3가지확인하라
대칭적?
추이성?
일관성?
equals()를 재정의할 땐, hashCode도 반드시 재정의하자
Object외의 타입을 매개변수로 받는 equals()는 작성하지말자!>> 이렇게하면 재정의(오버라이딩)아니라 오버로딩이다.
아이템 11. equals를 재정의하려거든 hashCode도 재정의
equals()를 재정의한 클래스 모두 hashCode()도 재정의해야한다
equals가 두 객체가 같다고 판단하면 반드시 hashCode()도 같은 판단나와야한다.
equals가 두 객체가 다르다 판단해도, hashCode()는 같을수도있다.(해쉬값충돌)
HashMap이나 HachSet에서 hashCode()씀..hashCode()재정의필요
hashCode(){return Objects.hash(…..)} 활용해도좋다.
그리고 hashCode()에 캐싱처리해놓는것도좋다
아이템 12. toString을 항상 재정의하라
Object의 기본 toString는 단순히 클래스 _이름@16진수로표시한해시코드를 반환한다
toString은 반드시 재정의해야한다. 그 객체가 가진 주요 정보를 모두 반환해주는 것 이좋다.>>읽기좋은형태로!
너무 정보가 방대하다면 해당객채가 가진특징요약도좋다 전화번호부(총 1234개)
상위 클래스에서 이미 알맞게 구현해놨다면 그대로써도된다.
toString가 어떤형식으로반환하는지 반드시 적어놔야한다.
아이템 13. clone 재정의는 주의해서 진행하라
Cloneable인터페이스는 매우 널리쓰인다.
하지만 final클래스가 아닌이상 다양한 상황을 고려해야한다 따라서 생성자와 팩터리를 이용하는 게 최고다
단 배열은 clone활용이 깔끔하다
아이템 14. Comparable을 구현할지 고려하라
Comparable 인터페이스의 유일한 메서드 compareTo!!!
compareTo는 Object메서드가 아니다
compareTo는 동치성 비교+순서비교+제니릭
Comparable을 구현했다 == 그 클래스의 인스턴스들에는 자연적 순서있음을 의미
따라서 Comparable을 구현한 객체의 배열은 Arrays.sort(a);처럼 손쉽게 정렬할수있다.
자바 플랫폼 라이브러리의 모든 값 클래스와 열거타입이 Comparable을 구현했다. 알파벳, 숫자, 연대등 순서가 명확한 값 클래스를 작성시 반드시 Comparable구현하자
비교를 활용하는 클래스 = TreeSet, TreeMap,
검색과 정렬 알고리즘 활용하는 Collections, Arrays
Comparable은 타입을 인수로 받는 제네릭 인터페이스 이므로, compareTo 메서드의 인수 타입은 컴파일타입에 정해진다.
Comparable을 구현하지 않은 필드나 표준이 아닌 순서로 비교해야한다면 Comparator를 대신 사용하자
4장 클래스와 인터페이스
추상화의 기본 단위인 클래스와 인터페이스
아이템 15. 클래스와 멤버의 접근 권한을 최소화하라
오직 API를 통해서만 다른 컴포넌트와 소통하며, 서로의 내부 동작방식에 전혀 개의치 않는다.<>> 캡슐화
장점은 많지만 핵심은 개별 컴포넌트 병행으로 개발가능, 동작 검증가능
각 요소의 접근성은 그 요소가 선언된 위치와 접근 제한자(4가지)로 정해진다.
기본원칙은 모든 클래스와 멤버의 접근성을 가능한 한 좁혀야한다.
가장 바깥의 톱레벨 클래스와 인터페이스에는 접근 수준이 2가지(package-private, public)가 존재한다 이중 public을 선언시, 공개 API가 되며, package-private선언시 , 해당 패키지 안에서만 이용가능하다. 즉, 외부에서 안사용하면 package-private바람직>> 내부 구현이므로, 클라이언트와 상관없이 수정, 교체, 제거가능.>> 반면 public일경우 API가되고, 하위 호환을 위해 영원한 관리 필요
멤버(필드,메서드, 중첩클래스,중첩 인터페이스) 에 부여할수있는 접근 수준 4가지
private: 멤버를 선언한 톱레벨 클래스에서만 접근가능
package-private(deflaut): 멤버가 소속된 패키지 안의 모든 클래스에서 접근가능
protected: package-private의 접근 버위 포함하고, 이 멤버를 선언한 클래스의 하위 클래스에서도 접근가능
public: 모든 곳에서 접근 가능
public클래스의 private 멤버를 package-private까지 풀어주는건 괜찮지만 그 이후까지 허용하지말자.
public클래스의 인스턴스 필드는 되도록 public이 아니여야 한다
아이템 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라
단순한 class {iv인스턴스} 는 데이터 필드에 직접 접근하기에 캡슐화 이점 제공못함>> 불변식을 보장못하고, 외부에서 필드에 접근할떄 부수 작업을 수행할수도없다. >> 따라서 private으로 모두 바꾼후, public 접근자(getter)를 추가한다
밖에서 접근가능한 클래스라면 접근자를 제공함으로 클래스 내부 표현 방식을 언제든 바꿀수있는 유연성을 얻음 public클래스가 필드를 공개하면 이를 사용하는 클라이언트들이 생겨날것이므로 내부 표현 방식을 마음대로 바꿀수없다.
하지만 package-private 클래스혹은 private 중첩 클래스라면 데이터 필드를 노출해도 문제없다.
public클래스의 가변 필드는 직접 노출 금지
아이템 17. 변경 가능성을 최소화하라
불변 클래스==그 인스턴스의 내부 값을 수정할수없는 클래스
만드는법 5가지
객체의 상태를 변경하는 메서드를 제공하지않는다
클래스를 확장할 수 없도록 한다
모든 필드를 final로 선언한다.
모든 필드를 private으로 선언한다.
자신 외에는 내부의 가변 컴포넌트에 접근할수없도록한다.
불변 객체이므로 메서드들의 반환은 결국 결과값을 담은 새로운 객체를 반환함
불변 객체는 생성된 시점부터 파괴될때까지 그대로 간직한다
불변 객체는 근복적으로 스레드 안전하여 따로 동기화할 필요없다.
불변 클래스는 자주 사용되는 인스턴스를 public static final 타입 변수명 = new 타입(자주쓰이는값) static으로 해주면, 캐싱!! 을 통해 , 중복해서 생성할 필요도없어진다.>>> 이런 정적 팩터리르 사용하면 여러 클라이언트가 인스턴스를 공유하여, 메모리 사용량, 가비지 컬렉션 비용줄어든다.
불변 객체의 단점은 값이 다르면 반드시 독립된 객체로 만들어야한다는 점이다.
따라서 getter구현한다고 setter를 무조건 만들지 말자
합당한 이유가 없다면 모든 필드는 private final 이여야한다
아이템 18. 상속보다는 컴포지션을 사용하라
상속은 코드를 재사용하는 강력한 수단이지만, 잘못사용하면 오류를 내기 쉽다
(지금부터 말하는 상속은 인터페이스 구현 X, 인터페이스 확장X) only 클래스가 클래스로 상속하는것
메서드 호출과 달리 상속은 캡슐화를 깨뜨린다( 상위 클래스 건드리면 하위클래스에서 문제발생ㄱ)
상속받은 애의 allAdd()메서드호출시 상속받은 애의 Add()를 호출하므로 allAdd()를 오버라이딩하지않았다면, 오류남… 상속은 즉, 상위 클래스의 내부 구현방식을 알수없다.
메서드 재정의만 문제아니다. 새로운 메서드를 추가하는것도 위험이다
상속의 취약점 피하려면 컴포지션과 전달을 사용하자.
아이템 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라
재정의 가능 메서드는 public과 protected메서드중 final이 아닌 모든 메서드를 뜻한다
상속을 고려하지 않았다면 하위 클래스에도 문제가 됨에 따라 금지하자
상속금지는 클래스를 final로 선언하거나, 생성자 모두를 외부 접근 금지하자
아이템 20. 추상 클래스보다는 인터페이스를 우선하라
추상 클래스와 인터페이스 차이를 보면, 추상클래스는 반드시 구현하는 클래스가 하위 클래스가 되어야한다는점이다(무조건 1개)
인터페이스는 믹스인 정의에 안성맞춤이다. >>믹스인이란, 대상 타입의 주된 기능에 선택적 기능을 혼합한다!는의미
인터페이스로는 계층구조없는 타입 프레임워크 만들수있다.
추상 골격 구현, 인터페이스 함께 제공.. 템플릿 메서드 패턴
아이템 21. 인터페이스는 구현하는 쪽을 생각해 설계하라
인터페이스는 디폴트 메서드가 들어갈수있게되었다.(하위 호환성때문에)
인터페이스에 함수추가나, 디폴트 메서드를 추가하는 일은 상당히 다양한 테스트 케이스 진행후 릴리스해야함
아이템 22. 인터페이스는 타입을 정의하는 용도로만 사용하라
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수있는 타입 역할을 한다.! 용도는 이것하나!!
상수 인스터페이스 안티패턴은 인터페이스를 잘못 사용한 예이다. 마치 내부 구현인 클래스의 상수를 API로 노출시키는 것과 같은 효과다
상수가 특정 클래스에 강하게 연관된 상수라면, 인스턴스화 할수없는 유틸리티 클래스에 담아서 공개하자(생성자를 private처리!!)
아이템 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라
상속을 이용하여, 각 상황에 맞게 동작이 달라지는 메서드를 루트 클래스의 추상 메서드로 선언 후 이를 상속받아 각각의 특성있는 클래스를 만든다. 공통인자들도 모두 루트 클래스로 보낸후, 이제 상속받아 특정 변수들은 그곳에서 정의
아이템 24. 멤버 클래스는 되도록 static으로 만들라
중첨 클래스란 다른 클래스 안에 정의된 클래서이며 자신을 감싼 바깥 클래스에서만 쓰여야한다!!
중첩 클래스
정적 멤버 클래스
멤버 클래스
익명 클래스
지역 클래스
첫번째 제외한 나머지는 내부 클래스에 해당된다.
정적 멤버 클래스는 흔히 바깐 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다
비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다. 따라서, 비정적 멤버 인스턴스안에서 바깥클래스명.this 형태로 가져올수있다.>> 비정적 멤버 클래스는 바깥 인스턴스없이는 생성불가능
따라서 개념사 ㅇ중첨 클래스의 인스턴스가 바깥 인스턴스와 독립적으로 존재가능하다면 정적 멤버 클래스로해야한다.
아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라
하나의 파일에는 하나의 톱레벨 클래스만 하자
5장 제네릭
아이템 26. 로 타입은 사용하지 말라
클래스와 인터페이스 선언에 타입 매개변수가 쓰이면, 제네릭 클래스 혹은 제네릭 인터페이스라한다.
제네릭 클래스와 제네릭 인터페이스를 통틀어 제네릭 타입이라고한다
각각의 제네릭 타입은 일련의 매개변수화 타입을 정의한다.! List (여기서 타입 매개변수 E에 해당하는 실제 타입 매개변수는 String이다)
제네릭 타입을 하나 정의하면 그에 따라른 로타입(raw type)도 함께정의된다. (로 타입== 하위호환성을 위해, 타입 매개변수 사용하지않았을때의 상황 을뜻함)