조슈아 블로크 님의 "Effective Java" 책을 정리한 포스팅 입니다.
1. 태그 달린 클래스보다는 클래스 계층구조를 활용하라
태그 달린 클래스
public class Shape {
// 태그 필드
public enum ShapeType { CIRCLE, RECTANGLE }
private final ShapeType type;
// CIRCLE에만 필요한 필드
private double radius;
// RECTANGLE에만 필요한 필드
private double width;
private double height;
// 생성자: 원
public Shape(double radius) {
this.type = ShapeType.CIRCLE;
this.radius = radius;
}
// 생성자: 직사각형
public Shape(double width, double height) {
this.type = ShapeType.RECTANGLE;
this.width = width;
this.height = height;
}
// 넓이를 계산하는 메서드
public double area() {
switch (type) {
case CIRCLE:
return Math.PI * radius * radius;
case RECTANGLE:
return width * height;
default:
throw new UnsupportedOperationException("Unknown shape type");
}
}
}
- 하위 클래스를 표시하는 값
- 클래스 계층구조를 흉내냄
단점
- 쓸데없는 코드가 많음
- 여러 구현이 한 클래스에 혼합되어 있음
- 가독성이 나쁨
- 오류를 내기 쉬움
클래스 계층구조
추상클래스 정의
- 루트가 될
- 태그 값에 따라 동작이 달라지는 메서드들을 추상 메서드로 정의
서브클래스 정의
- 가가자의 의미에 해당하는 데이터 필드를 넣음
- 루트 클래스가 정의한 추상 메서드를 각자의 의미에 맞게 구현
2. 멤버 클래스는 되도록 static으로 선언하라
중첩 클래스
- 다른 클래스 안에 정의된 클래스
정적 멤버 클래스
- 외부 클래스와 독립적
- 외부 클래스의 참조를 가지지 않아 메모리 누수가 방지됨
- 외부 클래스의 static 멤버만 접근 가능
- 관련 있는 클래스들을 논리적으로 묶기 위해 사용됨
- 사용 예
- Map.Entry: 논리적으로 묶고, Map과는 독립적으로 두어 외부 참조를 가지지 않도록 함
멤버 클래스
- 바깥 클래스의 인스턴스와 암묵적으로 연결됨
- 바깥 클래스의 모든 멤버에 접근 가능
- 바깥 인스턴스로의 숨은 외부 참조를 가지게 됨
- 이로 인해 메모리 누수가 날 수 있음
- 사용 예
- 어댑터를 정의할 때 자주 쓰임
- 자신의 반복자 구현
익명 클래스
- 쓰이는 시점에 선언과 동시에 인스턴스가 만들어짐
- 람다로 대체됨
지역 클래스
- 지역 변수가 선언되는 공간에 선언된 클래스
3. 톱레벨 클래스는 한 파일에 하나만 담으라
'Java' 카테고리의 다른 글
[Effective Java] 5-2. 제네릭: 권고 사항 (3) | 2024.12.28 |
---|---|
[Effective Java] 5-1. 제네릭: 제한 사항 (0) | 2024.12.27 |
[Effective Java] 4-3. 클래스와 인터페이스: 인터페이스 (0) | 2024.12.27 |
[Effective Java] 4-2. 클래스와 인터페이스: 상속보다는 컴포지션을 사용하라 (2) | 2024.12.27 |
[Effective Java] 4-1. 클래스와 인터페이스: 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2024.12.27 |