Java/이펙티브 자바
이펙티브 자바, 쉽게 정리하기 - item 12. toString을 항상 재정의하라
toString을 항상 재정의하라 toString() 메서드를 재정의해야 하는 이유 디버깅이 쉬워진다. 재정의하지 않으면 PhoneNumber@dbadd와 같이 클래스_이름@16진수_해시코드만 나온다. 재정의하면, 010-0000-0000과 같이 의미있는 정보를 볼 수 있다. 재정의 했다면, System.out.println(phoneNumber)와 같이 작성하면 내부 내용을 볼 수 있으므로 디버깅하기 쉽다. Map과 같은 경우, 내부에 많은 값을 가지고 있는데 toString()을 재정의하면 갖고 있는 모든 값을 알아내기에 매우 좋다. println(), printf(), + 연산자 등 toString() 메서드는 알게 모르게 많이 불려진다. 코딩이 쉬워진다. 만일 사용자에게 값을 보여줘야 할 일이 있..
이펙티브 자바, 쉽게 정리하기 - item 11. equals를 재정의하려거든 hashCode도 재정의하라
equals를 재정의하려거든 hashCode도 재정의하라. hashCode 일반 규약 equals()를 재정의한 클래스 모두에서 hashCode()도 재정의해야 한다. 그렇지 않으면, HashMap 혹은 HashSet의 원소가 되었을 때 문제가 발생할 수 있다. equals() 비교에 사용되는 필드가 변하지 않았다면, hashCode() 메서드는 몇번을 호출하든, 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 재시작한 경우에는 달라질 수 있다. equals(Object)가 두 값을 같다고 판단했다면, hashCode()의 반환 값도 같아야 한다. equals(Object)가 두 객체를 다르다고 판단했더라도, hashCode()가 달라질 필요는 없다. 단, 해시테이블 성능 최적화를 위해서 다르게 나오..
이펙티브 자바, 쉽게 정리하기 - item 10. equals는 일반 규약을 지켜 재정의하라
equals는 일반 규약을 지켜 재정의하라 equals() 메서드의 함정 기본적으로 객체의 내용이 동일한지 논리적 동치성을 확인하는 메서드이다. 하지만, 직접 구현하다보면 생각치 못한 여러가지 함정이 있으므로 직접 구현하지 않는 편이 안전하다. 구현하지 않아야 할 때 각 인스턴스가 본질적으로 고유할 때 ex) 스레드는 각각의 스레드가 고유하다. 인스턴스의 논리적 동치성을 검사할 일이 없을 때 상위 클래스에서 재정의한 equals()가 하위클래스에서도 문제없이 이용 가능할 때 ex) Map, Set은 AbstractMap, AbstractSet에서 내려받은 equals()를 그대로 사용한다. 클래스가 private 혹은 package-private일 때 논리적 동치성과 객체 식별성이 같은 의미를 가지게 될..
이펙티브 자바, 쉽게 정리하기 - item9. try-finally보다는 try-with-resources를 사용하라
try-finally보다는 try-with-resources를 사용하라 자바 라이브러리 내부의 close() 메서드 자바에서는 종종 .close() 메서드를 통해 자원을 닫아줘야 하는 경우가 있다. 주로 외부의 리소스를 사용했을 때이다. 외부의 리소스는 로컬 PC 환경에 존재하는 리소스일 수도 있고, 네트워크로 연결된 다른 컴퓨터에 존재하는 리소스(Connection)일 수도 있다. finalizer를 안전망으로 활용하긴 하지만, item8에서 배웠듯 딱히 믿을만하진 않다. try-finally를 이용하여 리소스 닫기 예제 1 - 반환할 자원이 1개일 때 static String firstLineOfFile(String path) throws IOException { BufferedReader br = ..
이펙티브 자바, 쉽게 정리하기 - item8. finalizer와 cleaner 사용을 피하라
finalizer와 cleaner의 사용을 피하라 자바가 제공하는 객체 소멸자 자바에서는 2가지 객체 소멸자를 제공한다. finalizer와 cleaner이다. 그러나, 이 두 소멸자는 기본적으로 쓰지 말아야 한다. 이후에 나오지만 try-catch-with-resources 방식이 권장된다. finalizer와 cleaner를 지양해야 하는 이유 가비지 컬렉터에 의해 실행이 결정되며, 즉시 실행된다는 보장은 없다. 객체에 접근하지 못하게 된 뒤로 finalizer나 cleaner가 실행되는데 얼마나 소요되는지 알 수 없다. finalizer와 cleaner가 즉시 실행된다는 보장이 없을 때 생기는 문제 ex) 시스템이 동시에 열 수 있는 파일의 갯수는 한정되어 있다. 열었던 파일을 닫아주지 않으면, 더..
이펙티브 자바, 쉽게 정리하기 - item7. 다 쓴 객체 참조를 해제하라
다 쓴 객체 참조를 해제하라 Stack 코드의 예제 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 pop() { if (size == 0) { throw new EmptyStackException(); } return elements[--size]; } pri..
이펙티브 자바, 쉽게 정리하기 - item6. 불필요한 객체 생성을 피하라
불필요한 객체 생성을 피하라 객체 생성의 비용 객체를 매번 생성하고 지우는 것은 반복적으로 발생했을 때 큰 비용이 될 수 있다. 물론 현대 컴퓨터의 성능이 많이 좋아서 작은 객체는 큰 부담이 되지 않을 수도 있다. 계속 같은 내용의 객체를 사용할 것이라면 불변 객체를 만들어놓고 재사용하는 것이 좋다. 불필요한 객체 생성의 예 String 객체의 예 String s = new String("bikini"); 위 코드는 안티패턴이다. 결국 bikini라는 문자열을 사용하고 싶은 건데, 굳이 JVM 문자열 풀에서 가져오지 않을 이유가 없다. String s = "bikini"; 더 간결하면서도 더 옳은 코드이다. Boolean 객체의 예 Boolean boolean = new Boolean(true); 과연 ..
이펙티브 자바, 쉽게 정리하기 - item5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 정적 유틸리티 클래스와 싱글턴 클래스의 남용 문제 정적 유틸리티 클래스로 구현한 맞춤법 검사기 살펴보기 public class SpellChecker { private static final Lexicon dictionary = ...; private SpellChecker() {} // 인스턴스 생성 방지 public static boolean isValid(String word) { ... } public static String suggestions(String typo) { ... } } 이전에 우리는 정적 유틸리티 클래스를 배웠다. 위의 코드는 정적 유틸리티 클래스를 활용한 맞춤법 검사기의 예이다. 싱글턴 클래스로 구현한 맞춤법 검사기 살펴보..
이펙티브 자바, 쉽게 정리하기 - item4. 인스턴스화를 막으려면 private 생성자를 사용하라
인스턴스화를 막으려면 private 생성자를 사용하라 인스턴스화를 막아야 하는 경우 유틸 클래스를 만들 때 java.lang.Math, java.util.Arrays, java.util.Collections와 같은 유틸 클래스를 구성하는 경우에는 해당 클래스가 쓸데없이 인스턴스화 되는 것을 막아야 한다. 객체지향적으로는 곱게 보이지 않을 수 있는 사용방식이다. 유틸 클래스 용도 1: 특정 인터페이스를 구현하는 객체 생성 팩토리 메서드를 모아놓는다. // from Collections 클래스 public static Map synchronizedMap(Map m) { return new SynchronizedMap(m); } Map 인터페이스 타입 객체를 넣으면, SynchronizedMap을 반환해주는 ..
이펙티브 자바, 쉽게 정리하기 - item3. private 생성자나 열거 타입으로 싱글턴임을 보증하라
private 생성자나 열거 타입으로 싱글턴임을 보증하라 싱글턴 패턴의 쓰임새 무상태 객체 (오직 메서드 실행을 위해 쓰이는 객체 등) 설계상 유일해야 하는 시스템 컴포넌트 싱글턴 패턴의 단점 싱글턴 객체를 사용하는 클라이언트의 테스트가 어려워짐 mock이 어려워진다. 싱글턴 구현법 생성자를 private으로 숨긴다. 인스턴스를 public static final 멤버에 생성해놓고 불러 쓴다. 인스턴스는 private static final 멤버에 넣어놓고, 공개된 public static 메서드로 불러 쓴다. INSTANCE 자체를 public으로 공개하기 public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elv..
이펙티브 자바, 쉽게 정리하기 - item2. 생성자에 매개변수가 많다면, 빌더 패턴을 고려하라
생성자에 매개변수가 많다면 빌더를 고려하라 생성자에 매개변수가 많다면? 영양 정보를 제공해야 하는데, 클래스 내부에 멤버 필드가 매우 많다고 가정하자. static class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; ... } 위 상황에서 경우의 수 별로 생성자로 만드는 것은 무리가 있다. 총 6개의 필드가 있고 이 중에 3개를 뽑는 것만 해도 경우의 수가 6*5*4/3*2가 나온다. 혹여나 만든다해도 실제 객체를 생성..
이펙티브 자바, 쉽게 정리하기 - item1. 생성자 대신 정적 팩터리 메서드를 고려하라
생성자 대신 정적 팩토리 메서드를 고려하라 핵심 요약 객체 생성에는 보통 생성자만 있다고 생각하기 쉽다. 정적 팩토리 메서드를 객체 생성 용도로 쓰는 것도 경우에 따라 좋다. 생성자 대신 정적 팩터리 메서드를 만들면 가지는 장점들 장점1: 생성자가 이름을 가질 수 있다. public class Test { @org.junit.jupiter.api.Test public void bigInteger() { BigInteger bigInteger = new BigInteger(10, 100, new Random()); BigInteger probablePrime = BigInteger.probablePrime(10, new Random()); System.out.println("bigInteger = " + ..