본문 바로가기
아카이브/자바의 정석

12장 지네릭스,열거형,애노테이션 20201112

by nineteen 2020. 11. 12.
반응형

지네릭 타입의 형변환

- 지네릭 타입과, 논지네릭 타입의 형변환은 가능 ( 경고 발생 )

- 지네릭 타입끼리 형변환 불가

- <String>이 <? extends Object>로 형변환 가능 ( 와일드카드 )

 

-> 타입이 지정된 지네릭 타입끼리는 형변환이 불가하지만 와일드 카드가 포함된 지네릭 타입으로 형변환은 가능

( 확인 되지 않은 타입으로의 형변환이라는 경고 발생 )

ex)

Optional<Object> -> Optional<T>, 형변환 불가

Optional<?> -> Optional<T>, 형변환 가능

 

 

 

지네릭 타입의 제거

- 컴파일러는 지네릭 타입을 이용해 소스파일 체크 후 필요한 곳에 형변환을 넣어주고 지네릭 타입을 제거

-> 컴파일된 파일(.class)에는 지네릭 타입에 대한 정보x, 지네릭 도입 이전의 소스 코드와의 호환성 유지위함

 

지네릭 타입의 제거 과정은 복잡해서 기본적인 제거과정에 대해서만 살펴본다

 

1. 지네릭 타입의 경계(bound)제거

1
2
3
4
5
class Box<extends Fruit> {
    void add(T t) {
    
    }
}
cs

 

                ↓ 

1
2
3
4
5
class Box {
    void add(Fruit t) {
    
    }
}
cs

 

2. 지네릭 타입을 제거한 후, 타입이 일치하지 않으면 형변환 추가

1
2
3
T get(int i) {
    return list.get(i);
}
cs

              ↓

1
2
3
Fruit get(int i) {
    return (Fruit)list.get(i);
}
cs

 

 

 

와일드 카드가 포함되어 있는 경우

1
2
3
4
5
6
static Juice makeJuice(FruitBox<extends Fruit> box) {
    String tmp ="";
    for(Fruit f : box.getList())
        tmp += f + " ";
    return new Juice(tmp);
}
cs

           ↓

1
2
3
4
5
6
7
8
static Juice makeJuice(FruitBox box) {
    String tmp ="";
    Iterator it = box.getList().iterator();
    while(it.hasNext()) {
        tmp += (Fruit)it.next() + " ";
    }
    return new Juice(tmp);
}
cs

 

 

 

 

 

 

 

열거형

- 서로 관련된 상수를 편리하게 선언하기 위한 것, 여러 상수를 정의할 때 사용하면 유용

- 열거형 상수를 사용하면 기존의 소스를 다시 컴파일하지 않아도 됨

( 기존엔 상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일해야 했음 )

 

 

 

열거형 정의와 사용

- 괄호{}안에 상수의 이름을 나열

ex)

enum Direction { EAST, SOUTH, WEST, NORTH }

- 열거형에 정의된 상수를 사용하는 방법은 '열거형이름.상수명' ( switch-case문에는 상수명만 사용 )

- 열거형 상수간의 비교에는 '=='를 사용가능, '<', '>'와 같은 비교연산자는 사용 불가 ( compareTo()는 사용가능 )

 

 

 

모든 열겨형의 조상 - java.lang.Enum

- values() : 열겨형의 모든 상수를 배열에 담아 반환

- ordinal() : 열겨형 상수가 정의된 순서(0부터 시작)를 정수로 반환

 

 

 

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
38
39
40
41
42
43
// 열거형 정의
enum Direction { EAST, SOUTH, WEST, NORTH }
 
public class EnumEx1 {
    public static void main(String[] args) {
        // 열거형 생성, 초기화
        Direction d1 = Direction.EAST;
        Direction d2 = Direction.valueOf("WEST");
        Direction d3 = Enum.valueOf(Direction.class"EAST");
        
        System.out.println("d1="+d1);
        System.out.println("d2="+d2);
        System.out.println("d3="+d3);
        
        System.out.println("d1==d2 ? " + (d1==d2));                        // '=='연산자 이용해 비교
        System.out.println("d1==d3 ? " + (d1==d3));
        System.out.println("d1.equals(d3) ? " + d1.equals(d3));            // equals()메소드 이용해 비교
//        System.out.println("d1 > d3 ? " + d1 > d3);                        // '<', '>'연산자 사용불가
        System.out.println("d1.compareTo(d3) ? " + (d1.compareTo(d3)));    
        System.out.println("d1.compareTo(d2) ? " + (d1.compareTo(d2)));    // 왼쪽이 크면 양수, 오른쪽이 크면 음수반환
        
        switch(d1) {
        case EAST :    // switch-case문에서는 상수명만 사용가능
            System.out.println("The Direction is EAST."); break;
        case SOUTH :
            System.out.println("The Direction is SOUTH."); break;
        case WEST :
            System.out.println("The Direction is WEST."); break;
        case NORTH :
            System.out.println("The Direction is NORTH."); break;
        default :
            System.out.println("Invalid direction."); break;
        }
        
        Direction[] dArr = Direction.values();                        // 열거형의 모든 상수를 배열로 담아 반환
        
        for(Direction d : dArr) {
            System.out.printf("%s=%d\n", d.name(), d.ordinal());    // 열거형 상수 이름과, 정의된 순서를 반환
        }
    }
 
}
 
cs

출력

d1=EAST

d2=WEST

d3=EAST

d1==d2 ? false

d1==d3 ? true

d1.equals(d3) ? true

d1.compareTo(d3) ? 0

d1.compareTo(d2) ? -2

The Direction is EAST.

EAST=0

SOUTH=1

WEST=2

NORTH=3