반응형

스터디 50

[Effective Java] Item10. equals는 일반 규약을 지켜 재정의

equals를 재정의하면 안되는 경우 각 인스턴스가 본질적으로 고유한 경우: 값을 표현하는 것이 아닌 동작하는 개체를 표현하는 경우 인스턴스의 '논리적 동치성'을 검사할 일이 없는 경우 상위 클래스에서 재정의한 equals가 하위 클래스에도 적용 가능한 경우 private 또는 packaage-private(default) 클래스이면서 equals메서드를 호출하지 않는 경우 그럼 언제 equals를 재정의할까요? 객체 식별성이 아니라 논리적 동치성을 확인해야 하는데, 상위 클래스의 equals로는 불가능한 경우. 주로 값 클래스들이 여기에 해당합니다. equals를 재정의할 때 지켜야 하는 규약 equals 메서드는 null이 아닌 개체 참조에 대해 등가 관계를 구현 null이 아닌 모든 ..

[Effective Java] Item 9. try-finally보다는 try-with-resource

try-finally static String firstLineOfFile(String path) throws IOException { BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } } 예외는 try와 finally 두 곳에서 발생할 수 있습니다. 예를들어서 기기에 물리적인 문제가 생긴다면 readLine()에서 예외를 던지고 close()또한 실패할 것입니다. 이 경우 close()에서 터진 예외가 readLine()의 예외를 완전히 집어삼켜서 해당 예외의 정보는 남지 않습니다. 물론, 두번째 예외(close()의 예외) 대신 첫번째 예외(re..

[Effective Java] Item 8. finalizer와 cleaner 사용을 피하라.

사용하지 마세요 finalizer는 예측할 수 없고, 상황에 따라 위험할 수 있습니다. 그래서 자바9 부터는 deprecated되었고 cleaner를 대안으로 소개합니다. 하지만 이 역시 finalizer보다는 덜 위험하지만, 예측할 수 없고, 느리고, 일반적으로 불필요합니다. 사용하지 말아야 할 이유 즉시 수행된다는 보장이 없습니다. 수행 여부도 보장하지 않습니다. 느립니다. finalizer를 사용한 클래스는 finalizer공격에 노출되어 보안문제를 일으킬 수도 있습니다. 대안 AutoCloseable을 구현하고, 인스턴스를 다 쓰고나면 close 메서드를 호출합니다.

[Effective Java] Item 7. 다 쓴 객체를 참조 해제하라.

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]; } private void ensureCapacity() { ..

[Effective Java] Item 6. 불필요한 객체 생성을 피하라

String str = new String("Hello"); String str2 = "Hello";String str = new String("Hello");가 실행될 때 마다 새로운 String 인스턴스를 만듭니다. 반면, String str2 = "Hello";는 여러번 실행되어도 새로운 인스턴스를 만들지 않고 오직 하나의 String 인스턴스를 만듭니다. 위와 같은 이유로 자바9부터는 Boolean의 생성자가 deprecated되었습니다. 이는 불변객체 뿐 아니라 가변객체라고 하더라도 사용중에 변경되지 않는다는 것이 확실하다면 재사용 할 수 있습니다. 객체 생성 비용이 비싼경우 매번 생성하는 것 보다는 재사용하는 것이 더 좋을 수 있습니다. static boolean isRomanNumeral(S..

[Effective Java] Item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용

의존 객체 주입 패턴 public SpellChecker { private static final Lexicon dictionary = new NaverLexicon(); } 이런 맞춤법 검사기가 있는 경우 DaumLexicon을 사용하거나 특수한 어휘사전을 사용할 수 없습니다. public SpellChecker { private static final Lexicon dictionary; public SpeelChecker(Lexicon dictionary) { dictionary = Objects.requireNonNull(dictionary); } } 위의 코드와 같이 생성자에 필요한 자원을 넘겨주는 방식을 사용하면 클리아이언트가 원하는 어휘사전을 사용할 수 있습니다. 이런 의존 객체 주입 패턴은 ..

[Effective Java] Item 4. 인스턴스화를 막으려면 private 생성자를 사용

인스턴스화를 막는 이유 java.lang.Math, java.util.Arrays처럼 기본 타입 값이나 관련된 메서드를 모아 놓을 때 java.util.Collections처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드를 모아 놓을 때 final 클래스와 관련된 메서드를 모아 놓을 때 인스턴스화를 막는 방법 public class UtilClass { //인스턴스화 방지용 private UtilClass() { throw new AssertionError(); } } 추상클래스는 하위 클래스를 만들어 인스턴스화 한다는 방법이 있으므로 private 생성자를 추가합니다. 이때 혹시라도 클래스 안에서 생성자를 호출하지 않도록 처리를 해줍니다. 이 방법은 상속을 불가능하게 하는 효과도 있습니다.

[Effective Java] Item 3. private 생성자나 Enum타입으로 싱글턴임을 보증하라

싱글턴(Singleton)? 객체의 인스턴스를 오직 1개만 생성할 수 있는 클래스를 말합니다. 싱글턴을 만드는 방법 private생성자 + public static 필드를 통해 인스턴스에 접근 private생성자 + 정적 펙토리 메서드 열거타입을 이용 public static 필드를 통한 싱글턴 생성 public class Printer { public static final Printer INSTANCE = new Printer(); private Printer() {} public void print() { System.out.println("위이잉~ 프린트 완료"); } } 장점 해당 클래스가 싱글턴인 것이 API에 명백하게 드러남 간결함 정적 펙토리 메서드를 통한 싱글턴 생성 public clas..

[Effective Java] Item 2. 생성자에 매개변수가 많다면 빌더

생성자에 매개변수가 많다면? 생성자(또는 정적 팩토리 메서드)는 선택적 매개변수가 많을 때 문제가 있습니다. public class User { private final String name; //필수 private final String birth; //필수 private final Integer height; //선택 private final Integer weight; //선택 public User(String name, String birth) { this(name, birth, null, null); } public User(String name, String birth, Integer height) { this(name, birth, height, null); } /* 컴파일에러 발생 (Use..

[Effective Java] Item 1. 생성자 대신 정적 팩토리 메서드를 고려하라

정적 펙토리 메서드(static factory method)란? 정적 펙토리 메서드에서 펙토리란 객체를 생성하는 역할을 이야기 합니다. 즉 객체를 생성하는 static method라고 생각하면 편합니다. 정적 팩토리 메서드의 장점(생성자와 비교하여) 이름을 갖는다. public class User { private String name; public User(String name) { this.name = name; } public static User nameOf(String name) { return new User(name); } public static void main(String[] args) { User user1 = new User("홍길동"); User user2 = User.nameOf..