개발/EffectiveJava 10

ITEM23 태그 달린 클래스보다는 클래스 계층구조를 활용하라.

정리 태그달린 클래스 : 두가지 이상의 의미를 표현할 수 있으며, 그중 현재 표현하는 의미를 태크값으로 알려주는 클래스 태그달린 클래스는 장황하고 오류를 내기 쉽고, 비효율적이다. 태그달린 클래스는 클래스 걔층구조를 어셜프게 흉내낸 아류일 뿐이다. 핵심정리 태그 달린 클래스를 써야 하는 상황은 거의 없다. 새로운 클래스를 작성하는 데 태그필트가 등장한다면 태크를 없애고 계층구조를 대체하는 방법을 생각해보자. 기존 클래스가 태그 필드를 사용하고 있다면 계층구조로 리펙터링 하는 걸 고민해보자.

ITEM21 인터페이스는 구현하는 쪽을 생각해 설계하라.

정리 자바 8 전에는 기존 구현체를 깨뜨리지 않고 인터페이스에 메서드를 추가할 방법이 없었다. 하지만 위험이 완전히 사라진 것은 아니다. 자바 8 에서는 핵심 컬렉션 인터페이스들에 다수의 디폴트 메서드가 추가되었다. 주로 람다를 사용하기 위해서다. 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어려운법이다. 디폴트 메서드는 컴파일에 성공하더라도 기존 구현체에 런타임 오류를 일으킬 수 있다. 핵싱은 명백하다. 디폴트 메서드라는 도구가 생겼더라도 인터페이스를 설계할 때는 여전히 세심한 주의를 기울여야한다.

ITEM20 추상 클래스보다는 인터페이스를 우선하라.

정리 인터페이스와 추상클래스의 가장 큰 차이는 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상클래스의 하위 클래스가 되어야한다는 점이다. 기존클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다. 반면 새로운 추상클래스를 끼워넣는 것은 어려운게 일반적이다. 인터페이스는 mixin 정의에 안성맞춤이다. mixin : 클래스가 구현할 수 있는 타입으로, 믹스인을 구현한 클래스에 원래의 '주된타입' 외에도 특정 선택정 행위를 제공한다고 선언한다는 효과를 준다. 대상의 주된 기능에 선택적기능으로 혼합한다고 해서 mixin 이라고 한다. 인터페이스로는 계층구조가 없는 타입 프레임워크를 만들 수 있다. 인터페이스는 기능을 향상시키는 안전하고 강력한 수단이 된다. 타입을 추상클래스로 정의..

ITEM19 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라.

정리 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지(자기사용) 문서로 남겨야한다. 재정의 가능이란 public protected 메서드중 final 이 아닌 모든 메서드를 뜻한다. 글래스의 내부 동작과정 중간에 끼어들수 있는 hook 을 잘 선별하여 proteced 메서드 형태로 공개해야 할 수도 있다. 상속용 클래스를 시험하는 방법은 직접 하위 클래스를 만들어보는 것이 유일하다. 상속용으로 설계한 클래스는 배포전에 반드시 하위 클래스를 검증해야 한다. 상속용 클래스의 생성자는 직접적으로든 간접적으로든 재정의 가능 메서드를 호출해서는 안된다. 정리 상속용 클래스를 설계하기란 결코 만만치 않다. 클래스 내부에서 스스로를 어떻게 사용하는지 모두 문서로 남겨야하며, 일단 문서화한 것..

ITEM18 상속보다는 컴포지션을 사용하라

정리 상속 : 클래스가 다른 클래스를 확장하는 구현상속을 의미(인터페이스 상속과는 무관) 상속은 코드를 재사용하는 강력한 수단이지만, 항상 최선은 아니다. 메서드호출과 달리 상속은 캡슐화를 깨뜨린다. 기존 클래스를 확장하는 대신, 새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조하게하자 기존 클래스가 새로운 클래스의 구성요소로 쓰인다는 뜻에서 이러한 설계를 컴포지션 이라한다. 새 클래스의 인스턴스 메서드들은 (private 필드를 참조하는 ) 기존 클래스의 대응하는 메서드를 호출해 그결과를 반환한다. 이 방식을 forwarding 이라 하며, 새 클래스이 메서드들을 forwarding method 라 부른다. // 래퍼 클래스 - 상속대신 컴포지션을 사용했다. public cla..

ITEM17 변경가능성을 최소화하라

정리 불변 클래스란 간단히 말해 그 인스턴스의 내부값을 수정할 수 없는 클래스다. String, 기분타입의 박싱된 클래스들, BigInteger, BigDecimal이 여기 속한다. 불변클래스는 갑녀클래스보다 설계하고 구현하고 사용하기 쉬우며, 오류가 생길 여지도 적고 안전한다. 규칙 - 객체의 상태를 변경하는 메서드(뼌경자)를 제공하지 않는다. - 클래스를 확장할 수 없도록 한다. - 모든 필드를 final로 선언한다. - 모든 필드를 private으로 선언한다. - 자신 외에는 내부의 가변컴포넌트에 접근할 수 없도록 한다. 불변 객체는 근본적으로 스레드 안전하여 따로 동기화할 필요 없다. 불변 객체는 안심하고 공유할 수 있다. 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터..

ITEM16 public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라.

정리 패키지 바깥에서 접근할 수 있는 클래스라면 접근자를 제공함으로써 클래스 내부 표현방식을 언제든 바꿀 수 있는 유연성을 얻을수 있다. 하지만 private-package 클래스 혹은 private 중첩 클래스라면 데이터 필드를 노출한다 해도 하등의 문제가 없다. public 클래스는 절대 가변필드를 직접 노출해서는 안된다. 불변 필드라면 노출해도 덜 위험하지만 완전히 안심할 수는 없다. 하지만 package-private 클래스나 private 중첩 클래스에서는 종종 필드를 노출하는 편이 나을 때도 있다.

ITEM15 클래스와 멤버의 접근권한을 최소화 하라.

모든 클래스와 멤버의 접근성을 가능한 한 좁혀야 한다는 것은, 소프트웨어가 올바로 동작하는 한 항상 가장 낮은 접근 수준을 부여해야 한다는 뜻이다. 멤버(필드, 메서드, 중첩 클래스, 중첩인터페이스)에 부여할 수 있는 접근 수준은 4가지다. private : 멤버를 선언한 톱래벨 클래스에서만 접근할 수 있다. package-private : 멤버가 소속된 패키지 안의 모든 클래스에서 접근할 수 있다. 접근 제한자를 명시하지 않았을때 적용되는 패키지 수준이다.(단, 인터페이스의 멤버는 기본적으로 public 이 적용된다.) protected : package-private 의 접근 범위를 포함하며, 이 멤버를 선언한 클래스의 하위클래스에서도 접근 할 수 있다. public : 모든곳에서 접근할 수 있다.

ITEM14 comparable 을 구현할지 고려하라

요점 compareTo 는 object 의 메서드가 아니다. 단순 동치성 비교에 더해 순서까지 비교할 수 있으며, 제네릭하고, equals 와 같다. 알파벳, 숫자, 연대 같이 순서가 명확한 값 클래스를 작성한다면 반드시 comparable 인테페이스를 구현하자. 일반규약 이 객체와 주어진 객체의 순서를 비교한다. 이 객체가 주어진 객체보다 작으면 음의 정수를, 같으면 0을 , 크면 양의 정수를 반환한다. 이 객체와 비교할 수 없는 타입의 객체가 주어지면 ClassCastException 을 던진다. Comparable 을 구현한 클래스는 모든 x, y에 대해 sgn(x.compareTo(y)) = - sgn(y.compareTo(x))여야 한다. Comparable 을 구현한 클래스는 추이성을 보장해야..