본문 바로가기

자바/이펙티브 자바10

[Item10] equals는 일반 규약을 지켜 재정의하라 equals 메소드를 재정의 하지 않으면 인스턴스는 오직 자기 자신과 같게된다. equals 메소드는 아래 열거한 상황에 해당되면 재정의 하지 않는 것이 좋다. Equals 재 정의를 피해야 하는 상황 각 인스턴스가 본질적으로 고유하다. 값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스가 여기 해당한다. 예) Thread 인스턴스의 논리적 동치성을 검사할 일이 없다. java.util.regex.Pattern은 equals를 재정의해서 두 Pattern의 인스턴스가 같은 정규표현식을 나타내는지를 검사하는, 즉 논리적 동치성을 검사하는 방법도 있다. (즉, 다른 정규표현식이더라도 논리적으로 동치인지 검사) 상위클래스에서 재정의한 equals가 하위 클래스에도 딱 들어맞는다. 대부분의 Set 구현체는.. 2020. 9. 8.
[Item9] try-finally보다는 try-with-resources를 사용하라. 자바 라이브러리에는 close 메소드를 호출해 직접 닫아줘야 하는 자원이 많다. 예를 들어, InputStream, OutputStream, java.sql.connection 등이 좋은 예다. 전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally 가 쓰였다. static String firstLineOfFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); }finally { br.close(); } } 문제점 1. try-finally가 중첩되면 지저분해질 수 있다. 나쁘지 않지만 자원을 하나 더 사용하게 되면.. 2020. 9. 8.
[Item8] finalizer와 cleaner 사용을 피하라 자바는 두가지 객체 소멸자를 제공한다. finalizer과 cleaner이다. finalizer와 cleaner는 GC될때 호출된다. finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있어 일반적으로 불필요하다. (자바9에서는 finalizer을 deprecated 시켰고 그 대안으로 cleaner을 제시했다.) cleaner는 finalizer보다는 덜 위험하지만, 여전히 예측할 수 없고, 느리고, 일반적으로 불필요하다. 자바의 finalizer와 cleaner는 c++의 destructor의 개념과 다르다. c++의 destructor는 특정 객체와 관련된 자원을 회수하는 보편적인 방법이다. 그러나 자바는 GC가 그 역할을 대신하고 프로그래머에게는 아무런 작업도 요구하지 않는다. c++의 .. 2020. 9. 7.
[Item7] 다 쓴 객체 참조를 해제하라 C, C++ 처럼 메모리를 직접 관리해야 하는 언어를 쓰다가 자바처럼 가비지 컬렉터를 갖춘 언어로 넘어오면서 프로그래머의 삶이 훨씬 평안해진다. 그래서 자칫 메모리 관리에 더 이상 신경 쓰지 않아도 된다고 오해할 수 있는데, 절대 사실이 아니다. 메모리를 직접 관리하는 클래스 스택을 간단히 구현한 다음 코드를 보자. 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) .. 2020. 9. 7.
[Item6] 불필요한 객체 생성을 피하라 똑같은 기능의 객체를 매번 생성하기보다는 객체 하나를 재사용하는 편이 나을 때가 많다. 재사용은 빠르고 세련됐다. 특히 불변객체(아이템17)는 언제든지 재사용할 수 있다. 생성자 대신 정적 팩토리 메소드 (아이템 1)를 제공하는 불변 클래스에서는 정적 팩토리 메소드를 사용해 불필요한 객체 생성을 피할 수 있다. 비싼 객체 예를 들어, Boolean(String) 생성자 대신 Boolean.valueOf(String) 팩토리 메서드를 사용하는 것이 좋다. 생성 비용이 아주 비싼 객체가 있다. 이런 '비싼 객체'가 반복해서 필요하다면 캐싱하여 재사용하길 권한다. 예를 들어, 주어진 문자열이 유효한 로마 숫자인지를 확인하는 메소드를 작성한다고 해보자. static boolean isRomanNumeral(St.. 2020. 9. 4.
[Item5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 많은 클래스가 하나 이상의 자원에 의존한다. 예를 들어 맞춤법 검사기는 사전에 의존하는데, 이 클래스는 정적 유틸리티 클래스(아이템4)나 싱글턴(아이템3)으로 구현하는 경우가 있다. public interface Lexicon { ... } // Lexicon의 구현체 public class EnglishDictionary implements Lexicon { ... } // 정적 유틸리티 클래스 public class SpellChecker { private static final Lexicon dictionary = new EnglishDictionary(); private SpellChecker() { ... } public static boolean inValid(String word) { ..... 2020. 8. 25.