목록이펙티브자바 (88)
도당탕탕
Nested class(이하 중첩 클래스)는 오직 Enclosing class(이하 동봉 클래스)를 돕기 위해서만 사용되어야 한다. 만약 그렇지 않으면 top level 클래스로 정의해야 한다. 4가지 종류의 중첩 클래스가 존재한다. static member class nonstatic member class anonymous class local class 여기서 2,3,4 번을 inner 클래스라고도 부른다. 1. Static member class 가장 흔한 사용은 오직 동봉 클래스와 연계해서 사용되는 public helper class이다. public class Calculator { // ... public static enum Operation { PLUS,MINUS; } } private ..
태그 값으로 알려주는 클래스는 단점이 많다. 다음 코드를 보면 알 수 있을 것이다. 태그 달린 클래스 class Figure { enum Shape { RECTANGLE, CIRCLE }; // tag 기능 final Shape shape; double length; double width; double radius; Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } Figure(double length, double width) { shape = Shape.RECTANGLE; this.length = length; this.width = width; } double area() { switch(shape) { case RECTA..
인터페이스를 만들 때는 클라이언트에게 어떤 일을 할 수 있는지 정보를 제공해야 한다. 이러한 규칙에 위배되는 것 중에 소위 constant interface라고 하는 것이 있다. 보통 아래와 같이 정의되고, 상수에 접근할 필요가 있는 클래스에서 인터페이스를 구현해서 사용한다. 이렇게 인터페이스에 상수를 정의하는 이유는 클래스 이름을 사용해서 지칭해야 할 필요가 없기 때문이다. public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.022_140_857e23; static final double BOLTZMANN_CONSTANT = 1.380_648_52e-23; static final double ELECTRON_MASS..
현재 자바 8 이전 버전에서는 기존 구현체를 깨트리지 않고는 인터페이스에 메서드를 추가할 방법이 없었다. 그래서 자바 8 이후에 디폴트 메서드를 통해 기존 인터페이스에 추가할 수 있도록 했다. 디폴트 메소드가 추가되면서 자바에서도 기존 인터페이스에 메서드를 추가하는 방법이 생겼지만 기존 구현체와 매끄럽게 연동이 되긴 힘들다. 그 이유는 구현 클래스에 대해 아무것도 모른 채 합의 없이 무작정 삽입시킬 수 있기 때문이다. 자바 8에서 핵심 컬렉션 인터페이스들에 다수의 디폴트 메소드가 추가되었다. 주로 람다를 활용하기 위해서다. 자바 라이브러리의 디폴트 메서드는 코드 품질이 높고 범용적이라 대부분 상황에서 잘 작동하지만 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메소드를 작성하기에는 어렵다. ..
먼저 추상화 클래스의 문제점부터 보자. 추상화 클래스를 상속하는 클래스는 다른 클래스를 상속받을 수 없다. 즉, 한 가지 타입에 종속되어 버린다. //TypeA.java public abstract class TypeA {} //TypeB.java public abstract class TypeB {} //TypeTest.java => 컴파일에러!! public class TypeTest extends TypeA,TypeB { } 반면 인터페이스는 mixin 을 정의하는데 이상적이다. 여기서 말하는 mixin 이란 Mixed In의 약자로 어느 한 인터페이스를 이미 구현하고 있는 클래스에서 새로운 인터페이스를 구현하여 새로운 선택적인 기능을 얻게 된다는 뜻이다. 추상 클래스는 두 개 이상 상속할 수 없기..
상속을 고려한 설계와 문서화란 정확히 말하면 다음과 같다. 상속을 고려한 설계와 문서화 메서드를 재정의하면 어떤 일이 일어나는지를 정확히 정리하여 문서로 남겨야 한다. 달리 말하면 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다. 클래스의 API로 공개된 메소드에서 클래스 자신의 또 다른 메서드를 호출할 수 있다. 그런데 마침 호출되는 메서드가 재정의 가능 메서드라면 그 사실을 호출하는 메서드의 API 설명에 적시해야 한다. 덧붙여서 어떤 순서로 호출하는지, 각각의 호출 결과가 이어지는 처리에 어떤 영향을 주는지도 담아야 한다. 즉 재정의 가능 메소드를 호출할 수 있는 모든 상황을 문서로 남겨야 한다. 대표적인 예로 @implSpec를 들 수 있다. Imple..
평범한 concrete 클래스(인스턴스를 만들 수 있는 완전한 클래스)를 상속하는 것은 위험하다. 슈퍼 클래스의 구현이 계속 바뀔 수 있고, 바뀌는 경우 서브 클래스가 더 이상 동작하지 않을 수 있다. 단 슈퍼클래스의 작성자가 상속을 목적으로 정의한 경우라면 상속해도 좋다. 부적절한 상속의 예는 아래와 같다. public class InstrumentedHashSet extends HashSet { private int addCount = 0; public InstrumentedHashSet(){} public InstrumentedHashSet(int initCap, float loadFactor) { super(initCap,loadFactor); } @Override public boolean ad..
불변 클래스란 인스턴스의 내부 값을 수정할 수 없는 클래스를 말한다. 불변 클래스가 가지고 있는 정보는 고정되어 객체가 없어지는 순간까지 절대 달라지지 않는다. 자바 라이브러리에서 가장 대표적인 불변 클래스가 String, primitve 타입의 박싱 된 클래스, BigIntegner, BigDecimal 등이 있다. 불변 클래스는 다음과 같은 장점이 있다. 바로 구현하고 사용하기 쉬우며, 오류가 생길 여지가 적어 훨씬 안전하다. 그럼 어떻게 불변을 만들지 알아보자. 불변 클래스의 다섯가지 규칙 클래스를 불변으로 만들려면 다음과 같이 5가지의 규칙을 따라야 한다. 객체의 상태를 변경하는 메서드를 제공하지 않는다. 클래스를 확장할 수 없도록 한다. ( 나쁜 의도로 객체의 상태를 변하게 만드는 사태를 막아주..