본문 바로가기

이펙티브 자바10

[아이템 10] equals는 일반 규약을 지켜 재정의해라 equals() 메서드를 함부로 재정의 하면 함정에 걸려 끔찍한 결과가 생길 수 있습니다. 문제는 회피하는 가장 쉬운 길은 equals() 메서드를 아예 재정의 하지 않는것입니다. 재정의 하지 않으면 인스턴스는 오직 자기 자신과만 같게 됩니다. 즉, 같은 주소값을 가진 객체와만 같게 됩니다. 아래에서 열거한 상황 중 하나에 해당하지 않는다면 재정의 하지 않는것이 최선입니다. 각 인스턴스가 본질적으로 고유하다. 값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스가 이에 해당합니다. Thread 가 좋은 예로, Object의 equals메서드는 이러한 클래스에 딱 맞게 구현되었습니다. 인스턴스의 '논리적 동치성(logical equality)'을 검사할 일이 없습니다. java.util.regex.Pa.. 2021. 5. 1.
[아이템 9] try-finally 보다는 try-with-resource를 사용하라 자바의 라이브러리에는 close 메서드를 호출해서 직접 닫아줘야 하는 자원이 많습니다. 직접 닫아줘야 하는 예로 InputStream, OutputStream, java.sql.Connection 등등이 있습니다. 자원 닫기는 라이브러리를 사용하는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어질 수 있습니다. 이런 자원 중 상당수가 finalizer 를 활용해서 안전망을 구현했지만 아이템8 을 보면 알 수 있듯 finalizer는 믿을만하지 못합니다. 이전에 자원이 제대로 닫힘을 보장하는 수단으로는 주로 try-finally가 쓰였습니다. 예외가 발생하거나 메서드에서 반환되는 경우를 포함해서 말입니다. 아래의 예제는 try-finally를 사용해서 자원을 해제하는 예제입니다. import .. 2021. 4. 25.
[아이템 8] finalizer와 cleaner 사용을 피하라 자바는 finalizer, cleaner 두 가지 객체 소멸자를 제공합니다. fianlizer finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어서 일반적으로 불필요합니다. -> 오동작, 낮은 성능, 이식성 문제의 원인이 되기도 합니다. 나름의 쓰임새가 있지만 기본적으로는 쓰지 않는것이 좋습니다. 자바9에서는 finalizer 사용을 Deprecated API로 지정하고 cleaner 사용을 대안으로 소개하고 있습니다. (하지만 자바 라이브러리에서도 여전히 finalizer를 사용하고 있습니다.) cleaner finalizer 보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로 불필요합니다. C++ 의 파괴자(destructor)와는 다른 개념입니다. C++의 파괴자는 특.. 2021. 4. 24.
[아이템 7] 다 쓴 객체 참조를 해제하라 C, C++같은 언어를 써본적은 없지만 해당 언어에는 가비지 컬렉터가 없어서 직접 메모리를 관리해야 한다고 들었습니다. 자바처럼 가비지 컬렉터를 갖춘 언어는 프로그래머의 삶을 편안하게 만들어줍니다. 다 쓴 객체의 메모리를 알아서 회수해가기 때문입니다. 이때문에 자칫 메모리 관리에서 더 이상 신경 쓰지 않아도 된다고 오해할 수 있는데, 이것은 사실이 아닙니다. package item7_20210424; import java.util.Arrays; import java.util.EmptyStackException; public class MyStack { private Object[] elements; private int size = 0; private static final int DEFAULT_INIT.. 2021. 4. 24.
[아이템 6] 불필요한 객체 생성을 피하라 똑같은 기능의 객체를 매번 생성하는것 보다 객체 하나를 재사용하는 편이 나을 때가 많습니다. 나중에 배울 불변 객체(아이템 17)은 언제든 재사용할 수 있습니다. 다음 코드는 사용하지 말아야할 극단적인 예시 입니다. public class AntiPatternEx1 { public static void main(String[] args) // 아래 s1 과 s2 는 각각 새로운 인스턴스를 생성한다. // 다른 객체로 활용하고 싶은게 아니라면 아래의 행위는 매우 쓸모없는 행위이다. String s1 = new String("charlie"); String s2 = new String("charlie"); System.out.println(s1 == s2); } } new String(String) 으로 생.. 2021. 4. 22.