개발서적/Effective Java

    [Effective Java] 멤버 클래스는 되도록 static으로 만들라

    중첩 클래스 중첩 클래스란 다른 클래스 안에 정의된 클래스를 의미한다. 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 한다. 중첩 클래스의 종류 정적 멤버 클래스, 멤버 클래스, 익명 클래스, 지역 클래스가 있으며 이 중 첫 번째를 제외한 나머지는 내부 클래스에 해당한다. 1. 정적 멤버 클래스 주로 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다. Calculator.Operation.PLUS Calculator.Operation.MINUS 2. 비정적 멤버 클래스 비정적 멤버 클래스의 인스턴스는 바깥 클래스의 인스턴스와 암묵적으로 연결된다. 그래서 비정적 멤버 클래스의 인스턴스 메서드에서 정규화된 this를 사용해 바깥 인스턴스의 메서드를 호출하거나 바깥 인스턴스의 참조..

    [Effective Java] 태그 달린 클래스보다는 클래스 계층구조를 활용하라

    태그 달린 클래스는 단점 한가득이다. 열거 타입 선언, 태그 필드, switch문 등 쓸데없는 코드가 많다. 여러 구현이 한 클래스에 혼합되어 있어서 가독성이 좋지 않다. 다른 의미를 위한 코드도 함께 하니 메모리도 많이 사용한다. 필드들을 final로 선언하려면 해당 의미에 쓰이지 않는 필드들까지 생성자에서 초기화해야 한다. 인스턴스 타입만으로는 현재 나타내는 의미를 알 길이 없다. => 태그 달린 클래스는 장황하고, 오류를 내기 쉽고, 비효율적이다. class Figure { enum Shape { RECTANGLE, CIRCLE }; final Shape shape; // 다음 필드들은 모양이 사각형일 때만 쓰인다 double length; double width; // 이 필드는 모양이 원(Cir..

    [Effective Java] 인터페이스는 타입을 정의하는 용도로만 사용하라

    인터페이스의 역할 인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 달리 말하면, 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에게 얘기해주는 것이다. 상수 인터페이스 상수 인터페이스는 인터페이스를 잘못 사용한 예다. 클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당한다. 따라서 상수 인터페이스를 구현하는 것은 이 내부 구현을 클래스의 API로 노출하는 행위다. 상수를 공개할 목적이라면 다음 선택지 중 하나를 택하는 것이 좋다. 클래스나 인터페이스 자체에 추가한다. - 특정 클래스나 인터페이스에 강하게 연관된 상수인 경우 적합하다 열거 타입 인스턴스화할 수 없는 유틸리티 클래스에 담아 공개한다. pu..

    [Effective Java] 인터페이스는 구현하는 쪽을 생각해 설계하라

    디폴트 메서드의 등장 자바 8에서 디폴트 메서드의 등장으로 기존 인터페이스에 메서드를 추가할 수 있게 되었다. 하지만 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 쉽지 않다. 예를 들어 Collection 인터페이스에 추가된 removeIf 메서드가 있다. 이 메서드는 if문의 조건이 true를 리턴하면 element를 제거하는 로직을 가지고 있다. 이 디폴트 메서드는 apache.commons.collections4.collection.SynchronizedCollection의 역할을 제대로 못하게 만든다. => 아파치 패키지는 객체에 락을 거는 기능을 추가적으로 제공하는데 Collection의 디폴트 메서드 추가로 이러한 약속이 쉽게 깨질 수 있게 되었다. 이런 문제..

    [Effective Java] 추상 클래스보다 인터페이스를 우선하라

    인터페이스의 장점 상속이 여러개 가능하기 때문에 믹스인이 가능하다. 계층구조가 불분명한 클래스들을 설계하기 유리하다. 래퍼 클래스와 함께 사용하면 인터페이스 기능을 향상 시키는 안전하고 강력한 수단이 된다. 구현이 명백한 것은 인터페이스의 디폴트 메서드를 사용해 프로그래머의 일감을 줄일 수 있다. default 메서드 인터페이스를 상속하면 인터페이스에 정의된 모든 메서드들을 구현해야 한다. 하지만 많은 외부 클래스가 이미 이 인터페이스를 사용하고 있다면 중간에 메서드를 삽입하는 것이 쉽지 않다. 이때, default 메서드를 이용할 수 있다. 구현이 명백한 것, 공통된 것은 인터페이스의 디폴트 메서드를 사용해 정의함으로써 인터페이스를 상속하여 사용할 프로그래머의 일감을 줄일 수 있다. 추상 클래스 자바8..