Item27. 비검사 경고를 제거하라

@SuppressWarnings

compiler 경고를 제거할수는 없지만 타입 안전하다고 확신할 수 있다면 @SuppressWarning(“unchecked”) annotation을 달아 경고를 숨길 수 있다, 단 rumtime에 ClassCastException이 발생하지 않도록 타입 안전함을 검증해야 한다.

Read more

Item26. Generic Raw Type은 사용을 자제하라

Generic Type

클래스와 인터페이스 선언에 타입 매개변수(type parameter)가 쓰이면 이를 generic class 또는 generic interface라 한다. 이 두 개를 통칭해서 Generic type이라고 부른다.

1
public class GenericExample<T>{} // T : 타입 매개변수 

각각의 generic type은 매개변수화 타입 (parameterized type)을 정의한다. 매개변수화타입은 <> 괄호 안에 실제 타입을 명시함으로서 정의가 가능하다.

1
GenericExample<String> stringGenericExample = new GenericExample<>();

raw tye은 generic type을 하나 정의하면 함께 정의되는데, generic type에서 타입 매개변수를 전혀 사용하지 않았을떄를 말한다. , raw type이 generic type을 하나 정의할떄마다 같이 생성되는 이유는 기존 java code와 호환성 문제떄문이다.

1
GenericExample rawTypeGeneric = new GenericExample();
Read more

State pattern

State Pattern (상태패턴)

객체의 다양한 상태를 객체화합니다.

객체 내부의 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있습니다
마치 객체의 class가 바뀌는 것과 같은 결과를 얻을 수 있습니다.

State Pattern 의 class diagram

먼저 객체의 여러 상태들에 대한 공통 인터페이스를 정의한다. 여기서는 State interface가 그 역할을 한다.

Context는 객체의 상태(State 객체)를 바꾸어가면서 다른 행동을 할 수 있는 클래스로, 여러개의 객체 상태를 가질 수 있다. request() method가 호출되면 그 작업은 상태 객체에게 위임(delegation)된다.

State 인터페이스를 구현한 실제 객체의 상태를 나타내는 Concrete State는 Context로 부터 요청된 작업을 수행한다 (handle() method )

Read more

Item25. top level class는 한 파일에 하나만 담으라

소스 파일 하나당 top-level class를 여러개 선언해도 compile error는 나지 않는다,

1
2
3
4
5
6
7
8
9
// Utensil.java 
class Utensil {

static final String NAME = "pan";
}

class Dessert{
static final String NAME = "cake";
}
1
2
3
4
5
6
7
8
class Dessert {

static final String NAME = "pie";
}

class Utensil {
static final String NAME = "pot";
}

위와 같이 하나의 java file에 여러개의 class가 들어있는 경우 문제가 생길수도 있다.

Read more

Item23. 태그 달린 class보다는 class 계층 구조를 활용하자

태그 달린 class

헌재 표현하는 의미를 태그 값으로 알려주는 class 는 아래와 같이 class 계층구조를 사용하지 않고, 한 class내에 태그 필드를 가지는 class를 말한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Figure {

enum Shape {RECTANGLE,CIRCLE};
// 현재 모양
final Shape shape;

// RECTANGLE일떄만 쓰이는 필드
double length;
double width;

// CIRCLE일떄만 쓰이는 필드
double radius;

// CIRCLE용 생성자
public Figure(double radius) {
this.shape = Shape.CIRCLE;
this.radius = radius;
}

// RECTANGLE용 생성자
public Figure(double length, double width) {
this.shape = Shape.RECTANGLE;
this.length = length;
this.width = width;
}

double area(){
switch (shape){
case RECTANGLE:
return length * width;
case CIRCLE:
return Math.PI * (radius * radius);
default:
throw new AssertionError(shape);
}
}
}
  • 태그 달린 class의 단점

  1. 태그 필드를 가지고, 분기처리 (swith,if-else)를 하기 때문에 코드 가독성이 떨어지고, 계층형 구조로 가져갔을때 불필요한 코드들이 생긴다.

  2. 태그 값마다 필요한 필드가 다른데, 이를 모두 하나의 class에 보관함으로, 객체를 생성하였을떄 사용되지 않는 필드 (메모리 낭비) 도 같이 초기화 된다.

  3. 변경에 열려있다, 태그 값 추가시마다 분기로직을 수정해야 한다.

  4. 인스턴스 타입을 보고 현재 타입이 나타내는 의미를 알 수가 없다.

Read more

Item22. 인터페이스는 타입을 정의하는 용도로만 사용하라

인터페이스의 사용 용도

인터페이스는 자신을 구현한 class의 instance를 참조할 수 있는 타입 역할을 한다.

즉 class가 어떤 인터페이스를 구현한다는 것은 자신의 인터페이스로 무엇을 할수 있을 지 client에게 얘기해주는 것이며, 인터페이스는 오직 이 용도로만 사용해야 한다.

Read more

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

추상 class

추상 class와 인터페이스의 가장 큰 차이점은 추상 class가 정의한 type을 구현하는 class는 반드시 추상 class의 하위 타입이 되야한다는 점이다.

java는 단일 상속만 지원함으로, 추상 class 방식은 새로운 타입을 정의하는데 제약을 갖게 된다. 반면 인터페이스의 경우는 어떤 class를 상속했더라도 같은 type으로 취급된다

기존 class에 새로운 인터페이스를 구현해넣는것은 쉬우나, 새로운 추상 class를 넣기는 힘들다.
두 class가 동일한 추상 class 를 확장하려면 그 추상 class는 계층구조상 두 class의 공통조상이여야 한다.

Read more