핵심 요약 순서를 고려해야 하는 클래스를 작성할 때, Comparable 인터페이스를 구현하여, 그 인스턴스들을 쉽게 정렬, 검색, 비교 기능을 제공하는 컬렉션과 어우러지도록 하자. 비교를 활용하는 클래스의 예는 정렬된 컬렉션인 TreeSet과 TreeMap, 검색과 정렬 알고리즘을 활용하는 유틸리티 클래스인 Collections와 Arrays가 있다. compareTo 메소드에서 필드의 값을 비교할 때, 연산자를 쓰면 안된다. 그 대신 박싱된 기본 타입 클래스가 제공하는 정적 compare 메소드나 Comparator 인터페이스가 제공하는 비교자 생성 메소드를 사용하자. Comparable 인터페이스 Comparable 인터페이스의 형태는 아래와 같다. public interface Comparable..
결말부터 보고 가자 ✍ Cloneable/clone의 단점 - 언어 모순적이다. - 생성자를 쓰지 않는 방식을 사용한다. - 엉성하게 문서화된 규약을 가진다. - 정상적인 final 필드 용법과 충돌한다. - 불필요한 검사 예외를 던진다. - 형변환이 필요하다. 단점이 상당하기 때문에 clone 대신에 대부분 복사 생성자와 복사 팩토리를 사용한다. 단, 배열을 복제하는 경우, final 클래스이며 별다른 문제가 없을 경우는 제외한다. 자바의 금쪽이 Cloneable/clone이 무엇인지 알아보자 Cloneable 인터페이스는 Object의 protected 메소드인 clone의 동작 방식을 결정한다. Cloneable을 구현한 클래스의 인스턴스에서 clone을 호출하면 그 객체의 필드들을 하나하나 복사한..
Object의 기본 toString 메소드는 별로 유용하지 않은 형태 클래스_이름@16진수로_표시한_해시코드를 반환한다. 해당 객체의 특징을 알려주도록 하위 클래스에서 toString을 재정의하면 디버깅이 매우 편리하다. equals와 hashCode만큼 중요하진 않지만.. 문서화 toString을 구현할 때 반환값의 포맷을 문서화하여 명확하게 정의하는 것이 좋다. 당연한 말이지만 다른 개발자들이 코드를 이해하고 디버깅하기에 편하기 때문 또 명시한 포맷에 맞는 문자열과 객체를 상호 전환할 수 있는 정적 펙토리나 생성자를 함께 제공하면 좋다. 객체->문자열로 변환하는 것 뿐만 아니라, 문자열->객체로 변환하는 것도 쉽게 할 수 있다 ! 반대로 문서화의 단점은 형태가 정해져 있기 때문에 유연성이 얻다는 거?..
equals를 재정의한 클래스는 hashCode도 재정의해야 한다. 그렇지 않으면 hashCode 일반 규약을 어기게 되어 HashMap나 HashSet같은 컬렉션의 원소로 사용할 때 문제가 발생한다. hashCode 일반 규약 1. equals 비교에 사용되는 정보가 변경되지 않았다면, hashCode도 변하면 안 된다. 2. equals가 두 객체가 같다고 판단하면, 두 객체의 hashCode는 똑같은 값을 반환한다. ⭐ 👉 논리적으로 같은 객체는 같은 해시코드를 반환해야 한다. 3. equals가 두 객체를 다르다고 판단하더라도, hashCode는 꼭 다를 필요는 없다. (but 다른 객체일 경우, 다른 값을 반환해야 해시테이블의 성능이 좋아진다) 2번 규약 : 논리적으로 같은 객체는 같은 해시코드..
결론 꼭 필요한 경우가 아니면 equals를 재정의하지 말자. 재정의해야 할 경우라면 클래스의 핵심 필드 모두, 다섯 가지 규약을 지켜가며 비교하자. equals 메소드를 재정의하지 않을 경우, 클래스의 인스턴스는 오직 자기 자신과만 같게 된다. 꼭 필요한 경우가 아니라면 재정의하지 말자. equals를 재정의하면 안 되는 경우 1. 각 인스턴스가 본질적으로 고유할 때 값 클래스(ex. Integer, String 등)가 아닌 동작하는 개체를 표현하는 클래스(ex. Thread)를 말한다. 앞서 말했듯, 이런 클래스의 경우 이미 Object의 equals 메소드에서 구현되어 있다. 2. 인스턴스의 논리적 동치성을 검사할 일이 없을 때 당연한 말이다. 그렇지 않은 경우는 Object의 equals 메소드에..
결론적으로 이 책에서는 모든 경우에서 try-finally를 사용하지 말고 자바 7에 도입된 try-with-resources를 사용하라고 권장한다. 아래에서 그 이유에 대해 알아보자. 자바 라이브러리에는 InputStream, OutputStream, java.sql.Connection처럼 close 메소드를 호출해야 하는 리소스가 많다. 클라이언트에서 직접 호출 클라이언트 코드에서 놓치는 경우가 많아 성능 문제가 발생한다. (까먹을 수도, 예외 발생으로 처리가 안될 수도..) 아래 코드로 예시를 들면, br.readLine() 메소드에서 IOException이 발생할 경우, close는 호출되지 않고 스트림이 메모리에 남게 된다. public static String inputString() thro..
자바에서 객체 소멸자는 finalizer와 cleaner가 있다. 둘 다 예측할 수 없고, 위험할 수 있으며, 일반적으로 불필요하다. (cleaner가 비교적 덜 위험하다고는 함) C++ 파괴자 vs 자바 finalizer와 cleaner 책에서는 두 개념이 같은 것이라고 오해하지 않도록 비교해준다. (가볍게 넘어가도 될 듯 함) C++의 파괴자는 객체와 관련된 자원을 회수하는 용도와 비메모리 자원을 회수하는 용도로 사용된다. 반면 자바는 전자는 가비지 컬렉터를, 후자는 try-with-resources와 try-finally를 사용해 해결한다.(아이템 9) *try-with-resources 더보기 try-with-resources는 자동으로 AutoCloseable 인터페이스를 구현한 리소스를 해제하..
자바는 가비지 컬렉터가 있기 때문에 메모리 관리에 신경 쓰지 않아도 생각하기 쉽지만 그렇지 않다. 이 책에서는 자기 메모리를 직접 관리하는 클래스, 캐시, 리스터 또는 콜백의 경우에는 메모리 관리를 주의해야 한다고 설명한다. 메모리 누수의 주범인 위 세 가지 경우에서 메모리 누수가 발생하는 원인과 해결 방법에 대해 알아보자. 1. 자기 메모리를 직접 관리하는 클래스 다음 코드를 살펴보자. elements 배열로 저장소 풀을 만들어 원소들을 관리하기 때문에, 자기 메모리를 직접 관리하는 클래스임을 알 수 있다. public class Stack { ... public Object pop() { if (size == 0) throw new EmptyStackException(); return elements..