Box<? extends Number> box
위의 와일드 카드 선언은
"Box class의 type parameter를 Number와 Number의 하위 타입으로 제한한다."는 문법적 의미
를 지닌다.
Box<? extends Number> box
결론부터 말하자면 box가 참조하는 대상으로 꺼내는 작업만 허용하겠다는 의미이다.
즉, box의 method중 parameter에 Type parameter(ex. T)가 정의 되어 있는 경우 그 method들을 사용하지 못하게 제한하겠다는 의미이다.
그렇다면 왜 "? extends Number"라는 선언이 이러한 암시적인 의미를 지니게 되는 것일까?
이는 문법적 의미를 생각해 보면 알 수 있다.
만약 Box 클래스가 다음과 같이 이루어져 있다면
class Box<T> {
private T content;
public void setContent(T content){ this.content = content } // Box Method-(1)
public T changeToy(T newToy){ // Box Method-(2)
T oldToy = this.content;
this.content = newToy;
return oldToy;
}
public T getContent(){ return this.content } // Box Method-(3)
}
다음과 같은 제네릭 메소드를 사용 할 때
public static void unBox(Box<? extends Toy> box){
box.setContent(new Toy()); // Generic Method-(1)
}
(1)과 같이 box에 실수로 값을 넣으려 할 경우 컴파일 에러가 발생하게 된다.
이렇게 되는 이유는 box의 type 변수가 Toy를 상속하는 것은 맞지만 구체적으로 어떠한 type인지는 알 수 없기 때문이다.
public static void unBox(Box<? extends Toy> box){
Toy content = box.getContent(); // Generic Method-(2)
}
반면, (2)와 같이 box에서 값을 가져오고자 할 경우에는 구체적인 type을 알 수는 없지만 box에서 나올 type은 Toy의 subtype이기 때문에 정상적으로 수행이 가능하다.
좀 더 확장해서 생각해 본다면 Box Method-(1) 또는 (2)의 경우 type parameter(T)를 method의 parameter로 가지고 있다.
이러한 method를 사용하게 될 경우 Box Method-(1),(2)의 paramter로 사용 될 수 있는 값들은 type 자체를 확정 할 수 없기 때문에 애초에 함수를 호출 하는 것이 불가능 하다.
한가지 확실 하게 알 수 있는 것은 Box Method-(3)과 같이 type parameter를 method의 반환 값으로 사용 할 경우 그 값은 반드시 Toy의 subtype이라는 것이다.
lower bounded wild card 예시
Box<? super Number> box
"Box class의 type parameter를 Number와 Number의 상위 타입으로 제한한다."는 문법적 의미를 지닌다.
Box<? super Number> box
결론부터 말하자면 box가 참조하는 대상으로 넣는 작업만 허용하겠다는 의미이다.
즉, box의 method중 반환값에 Type parameter(ex. T)가 정의 되어 있는 경우 그 method들을 사용하지 못하게 제한하겠다는 의미이다.
그렇다면 왜 "? super Number"라는 선언이 이러한 암시적인 의미를 지니게 되는 것일까?
이는 문법적 의미를 생각해 보면 알 수 있다.
다음과 같은 제네릭 메소드를 사용 할 때
public static void box(Box<? super Toy> box){
Toy toy = box.getContent(); // Generic Method-(3)
}
Generic Method-(3)과 같이 box에 실수로 값을 넣으려 할 경우 컴파일 에러가 발생하게 된다.
이렇게 되는 이유는 box의 type 변수가 Toy의 상위 type인 것은 맞지만 구체적으로 어떠한 type인지는 알 수 없기 때문이다.
public static void box(Box<? super Toy> box){
box.setContent(new Toy()); // Generic Method-(4)
}
반면, (4)와 같이 box에 값을 넣고자 할 경우에는 구체적인 type을 알 수는 없지만 box가 가진 type이 Toy의 상위 클래스인 것은 확실히 알 수 있기 때문에 컴파일 에러가 발생하지 않는다.
좀 더 확장해서 생각해 본다면 Box Method-(1) 또는 (2)의 경우 type parameter(T)를 method의 parameter로 가지고 있다.
Box Method-(3)과 같이 type parameter를 method의 반환 값으로 사용 할 경우 그 값이 구체적으로 어떠한 Type인지 알 수 없다. 알 수 있는 정보라고는 Object를 상속하는 type이라는 정보 뿐이다.
반면, 한가지 확실 하게 알 수 있는 것은 Box Method-(1),(2)의 paramter로 사용 될 수 있는 값들은 type이 항상 Toy의 상위 클래스이기 때문에 Toy를 항상 정상적으로 받을 수 있다는 것이다.
Box<? extends Number> box
절대 모르는 것 : box가 참조하고 있느 Box 객체의 Method의 parameter의 Type
확실하게 알 수 있는 것 : box가 참조하고 있는 Box 객체의 Method의 반환형
Box<? super Number> box
절대 모르는 것 : box가 참조하고 있는 Box 객체의 Method의 반환형
확실하게 알 수 있는 것 : box가 참조하고 있느 Box 객체의 Method의 parameter는 항상 Number의 상위 Type이다.
윤성우의 열혈 Java Programming