Book/Effective Java
-
[Effective Java] Item 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라Book/Effective Java 2024. 11. 30. 11:15
태그 달린 클래스태그 달린 클래스란 두 가지 이상의 의미를 표현하며, 그 중 현재 표현하는 의미를 태그 값으로 알려주는 클래스다. 예시 코드를 살펴보자.public class Figure { enum Shape {RECTANGLE, CIRCLE} //태그 필드 - 현재 모양을 나타낸다. private Shape shape; // 다음 필드들은 모양이 사각형일 때만 사용. private double length; private double width; // 다음 필드들은 모양이 원일 때만 싸용. private double radius; //원용 생성자 public Figure(double radius) { shape = Shape.CIRCL..
-
[Effective Java] item 22. 인터페이스는 타입을 정의하는 용도로만 사용하라Book/Effective Java 2024. 11. 29. 21:45
인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에 얘기해주는 것이다. 이렇게 인터페이스는 오직 타입을 정의하는 용도로만 사용해야 한다. 상수 인터페이스하지만 이 지침에 맞지 않는 예로 상수 인터페이스라는 것이 있다. 상수 인터페이스란 메서드 없이, 상수를 뜻하는 static final 필드로만 구성된 인터페이스를 말한다. 예시로는 다음과 같다.public interface PhysicalConstants { static final double AVOGADROS_NUMBER = 6.022_104_857e23; static final double BOLTZMANN_CONSTANT = ..
-
[Effective Java] item 21. 인터페이스는 구현하는 쪽을 생각해 설계하라Book/Effective Java 2024. 11. 28. 21:55
자바8 전에는 기존 구현체를 깨뜨리지 않고는 인터페이스에 메서드를 추가할 수 없었지만, 디폴트 메서드가 나오면서 이를 해결할 수 있게 되었다. 하지만 위험성이 완전히 사라지지 않았다. 그 이유는 디폴트 메서드를 선언하면, 재정의하지 않아도 그 인터페이스를 구현한 모든 클래스에서 디폴트 구현이 쓰인다. 이것이 모든 기존 구현체들과 매끄럽게 연동되리라는 보장이 없기 때문이다. 디폴트 메서드들은 코드 품질이 높고 범용적이라 잘 작동하지만, 생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하는 것을 어렵다. 이번 아이템에서는 디폴트 메서드 사용 시 주의해야할 점들에 대해 알려준다. 모든 클라이언트에 대해 고려되지 않을 수 있다자바8의 Collection 인터페이스에는 removeIf가 추..
-
[Effective Java] item 20. 추상 클래스보다는 인터페이스를 우선하라Book/Effective Java 2024. 11. 27. 22:05
자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상클래스가 있다. 자바 8부터 디폴트 메서드가 생겨 두 메커니즘 모두 인스턴스 메서드를 구현 형태로 제공할 수 있게 되었다. 이 둘의 가장 큰 차이점은 다음과 같다.추상 클래스추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다.인터페이스선언한 메서드를 모두 정의하고 그 일반 규약을 잘 지킨다면 같은 타입으로 취급된다.하기 코드를 보면 이해하기 쉬울 것이다.public class SingerSongwriter extends Song implements Singer { ... }public class DanceSinger extends Dance implements Singer { ... }public static..
-
[Effective Java] item 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라Book/Effective Java 2024. 11. 26. 22:01
아이템18에서는 상속을 염두하지 않고 설계된 클래스를 상속했을 때의 위험성을 알려줬다면, 이번 아이템에서는 상속을 고려하여 설계하고 문서화해야 하는 방법을 알아보자. 문서를 남기자우선, 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지 문서로 남겨야 한다. 재정의 가능한 메서드가 어떤 순서로 호출하는지, 각각의 호출 결과가 이어지는 처리에 어떤 영향을 주는지도 담아야 한다. 상속을 위해서는 문서를 남기는 것이 좋다. API 문서의 메서드 설명 끝에 종종 “Implementation Requirements”로 시작하는 절을 볼 수 있는데, 그 메서드의 내부 동작 방식을 설명하는 곳이다. 이 절은 메서드 주석에 @implSpec 태그를 붙여주면 자바독 도구가 생성해준다. 다음은 jav..
-
[Effective Java] item 18. 상속보다는 컴포지션을 사용하라Book/Effective Java 2024. 11. 25. 22:10
인터페이스가 아닌 구현된 클래스를 상속받는 행위는 캡슐화를 깨뜨린다. 이에 대한 예시로, 추가된 원소 수를 저장하는 기능을 추가한 HashSet을 살펴보자.public class InstrumentedHashSet extends HashSet { private int addCount = 0; ... @Override public boolean add(E e) { addCount++; return super.add(e); } @Override public boolean addAll(Collection c) { addCount += c.size(); return super.addAll(e); } public int getAddCount() { return addCount; }} 이 클래스의 인스턴..
-
[Effective Java] item 17. 변경 가능성을 최소화하라Book/Effective Java 2024. 11. 24. 12:05
자바 플랫폼 라이브러리에는 다양한 불변 클래스가 있다. 대표적으로 String, 기본 타입의 박싱된 클래스들, BigInteger, BigDecimal이 있다. 이러한 불변 클래스는 가변 클래스보다 설계, 구현, 사용이 쉬우며 오류가 생길 여지도 적고 훨씬 안전하다. 클래스를 불변으로 만들기 위해서 다음 다섯 가지 규칙을 따르면 된다.객체의 상태를 변경하는 메서드(변경자)를 제공하지 않는다.클래스를 확장할 수 없도록 한다.모든 필드를 final로 선언한다.모든 필드를 private으로 선언한다.자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 한다. 불변 클래스는 다음과 같은 장점이 있기 때문에 사용한다.불변 객체는 단순하다.불변 객체는 근본적으로 스레드 안전하여 따로 동기화할 필요가 없다. 따라서 ..
-
[Effective Java] item 16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라Book/Effective Java 2024. 11. 24. 10:50
자바 플랫폼 라이브러리에도 public 클래스 필드를 직접 노출시킨 사례가 있는데, 그 대표적인 예가 Point와 Dimension 클래스다. 실제로 Dimension 클래스는 이때문에 아직까지 심각한 성능 문제를 해결하지 못하고 있다고 한다. 그러므로 public 클래스 작성 시, 필드를 모두 private으로 하고 public 접근자(getter)와 변경자(mutator/setter) 메서드를 추가하여 캡슐화해야한다. 이렇게 했을때의 장점은 다음과 같다.캡슐화의 이점을 얻을 수 있다. (코드 중복 줄이고 동작 방식을 외부가 알 필요가 없음)API를 수정하지 않고 내부 표현을 바꿀 수 있다.불변식을 보장한다.외부에서 필드에 접근할 때, 부수 작업을 수행할 수 있다.하지만 package-private 클..