Book
-
Item 13. clone 재정의는 주의해서 진행하라Book/Effective Java 3E 2022. 10. 19. 20:00
Cloneable 인터페이스는 Object의 protected 메서드인 clone의 동작 방식을 결정합니다. Cloneable을 구현한 클래스의 인스턴스에서 clone을 호출하면 그 객체의 필드들을 하나하나 복사한 객체를 반환하며, 그렇지 않은 클래스의 인스턴스에서 호출하면 CloneNotSupportedException을 던집니다. 인터페이스를 구현한다는 것은 일반적으로 해당 클래스가 그 인터페이스에서 정의한 기능을 제공한다고 선언하는 행위인데, Cloneable의 경우에는 상위 클래스에 정의된 protected 메서드의 동작 방식을 변경한 것으로 상당히 이례적으로 사용한 예입니다(따라 하지 말것!). Object 명세 이 객체의 복사본을 생성해 반환한다. '복사'의 정확한 뜻은 그 객체를 구현한 클래..
-
Item 12. toString을 항상 재정의하라Book/Effective Java 3E 2022. 10. 18. 21:30
toString의 일반 규약에 따르면 '간결하면서 사람이 읽기 쉬운 형태의 유익한 정보'를 반환해야 합니다. 또한 toString의 규약은 "모든 하위 클래스에서 이 메서드를 재정의하라"고 합니다. 실전에서 toString은 그 객체가 가진 주요 정보 모두를 반환하는 게 좋습니다. 하지만 객체가 거대하거나 객체의 상태가 문자열로 표현하기에 적합하지 않다면 요약 정보를 담아야 합니다. toString을 구현할 때면 반환값의 포맷을 문서화할지 정해야 합니다. 전화번호나 행렬 같은 값 클래스라면 문서화하기를 권합니다. 포맷을 명시하면 그 객체는 표준적이고, 명확하고, 사람이 읽을 수 있게 됩니다. 포맷을 명시하기로 했다면, 명시한 포맷에 맞는 문자열과 객체를 상호 전환할 수 있는 정적 팩터리나 생성자를 함께 ..
-
Item 11. equals를 재정의하려거든 hashCode도 재정의하라Book/Effective Java 3E 2022. 10. 18. 20:40
equals를 재정의한 클래스 모두에서 hashCode도 재정의해야 합니다. 그렇지 않으면 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것입니다. Object 명세 규약 equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관없다. equals(Object)가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다. equals(Object)가 두 객체를 다르다고 판단했더라도, 두 객체의 hashC..
-
Item 10. equals는 일반 규약을 지켜 재정의하라Book/Effective Java 3E 2022. 10. 17. 06:28
equals 메서드는 재정의하기 쉬워 보이지만 곳곳에 함정이 있어 자칫하면 끔찍한 결과를 초래합니다. 문제를 회피하는 가장 쉬운 길은 아예 재정의하지 않는 것입니다. 다음에 열거한 상황 중 하나에 해당한다면 재정의하지 않는 것이 최선입니다. 각 인스턴스가 본질적으로 고유하다. 값을 표현하는(Integer, String 등) 게 아니라 동작하는 개체를 표현하는 클래스가 여기 해당한다. (예: Thread) 인스턴스의 '논리적 동치성(logical equality)'을 검사할 일이 없다. 상위 클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다. 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없다. 위험을 철저히 회피하는 스타일이라 equals가 ..
-
Item 9. try-finally보다는 try-with-resources를 사용하라Book/Effective Java 3E 2022. 10. 13. 08:30
자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많습니다. InputStream, OutputStream, java.sql.Connection 등이 좋은 예입니다. 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 합니다. 이런 자원 중 상당수가 안전망으로 finalizer를 활용하고 있지만 finalizer는 그리 믿을만하지 못합니다(Item 8). 전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였습니다. 예외가 발생하거나 메서드에서 반환되는 경우를 포함해서 말입니다. package effectivejava.chapter2.item9.tryfinally; import java.io.BufferedReader; import..
-
Item 8. finalizer와 cleaner 사용을 피하라Book/Effective Java 3E 2022. 10. 13. 08:00
자바는 두 가지 객체 소멸자를 제공합니다. 다만, 두 가지 객체 소멸자 모두 예측할 수 없고, 일반적으로 불필요합니다. finalizer: 자바 9 deprecated API 지정. cleaner를 대안으로 소개. cleaner: 자바 9부터 지원하는 객체 소멸자. finalizer와 cleaner는 즉시 수행된다는 보장이 없습니다.[JLS, 12.6] 즉, finalizer와 cleaner로는 제때 실행되어야 하는 작업은 절대 할 수 없습니다. 자바 언어 명세는 finalizer나 cleaner의 수행 시점뿐 아니라 수행 여부조차 보장하지 않습니다. 따라서 프로그램 생애주기와 상관없는, 상태를 영구적으로 수정하는 작업에서는 절대 finalizer나 cleaner에 의존해서는 안 됩니다. 또한, fina..
-
Item 7. 다 쓴 객체 참조를 해제하라Book/Effective Java 3E 2022. 10. 12. 22:07
아래 코드는 스택을 간단히 구현한 코드입니다. package effectivejava.chapter2.item7; import java.util.*; // 코드 7-1 메모리 누수가 일어나는 위치는 어디인가? public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object po..
-
Item 6. 불필요한 객체 생성을 피하라Book/Effective Java 3E 2022. 10. 10. 09:32
똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많습니다. 특히 불변 객체는 언제든 재사용할 수 있습니다. String s = new String("bikini"); // 따라 하지 말 것! 위 문장은 실행될 때마다 String 인스턴스를 새로 만듭니다. 완전히 쓸데없는 행위입니다. 반복문이나 빈번히 호출되는 메서드 안에 있다면 쓸데없는 String 인스턴스가 수백만 개 만들어질 수도 있습니다. String s = "bikini"; 위 코드는 하나의 String 인스턴스를 사용합니다. 나아가 이 방식을 사용한다면 같은 가상 머신 안에서 이와 똑같은 문자열 리터럴을 사용하는 모든 코드가 같은 객체를 재사용함이 보장됩니다.[JLS, 3.10.5] 생성자 대신 정적 팩터리 메서..