가자미의 개발이야기

[Java] 자바 와일드카드 본문

Java/자바 기본 문법

[Java] 자바 와일드카드

가자미 2021. 1. 22. 17:35

a. 와일드카드

위가 제네릭 메소드, 아래가 와일드카드 메소드이다.

기능적으로는 동일하지만 와일드카드가 더 간결하므로 와일드 카드를 선호한다.

 

제네릭 타입에 다형성을 적용하기 위함.

표현 와일드카드 종류 설명
<?> 와일드카드 제한 없음. 모든 타입 가능
<? extends Object>와 동일
<? extends T> 상한 제한 와일드카드 T와 그 자손들만 가능
<? super T> 하한 제한 와일드카드 T와 그 조상들만 가능

 

b. 상한 제한된 와일드카드

제네릭 클래스의 상속과 같이 타입매개변수를 extends로 제한하는 기능이다.

이 경우 box의 타입은 Number Integer Double로 제한된다.

가장 상위 클래스를 제한하는 의미

 

b-1. 상한 제한의 목적

outBox는 와일드카드 상한제한을 통해 set에 new Toy가 들어가는 오류를 막는다!

왜 막을까?

만약 Toy의 자식인 Car가 매개변수 타입이라고 생각하자. 그렇다면 box의 타입은?

당연히 Car이다.

그런데 box.set(new Toy())?

Car ob=new Toy()가 불가능하다!!!(상속개념)(안전성 상승)

쉽게 Box<? extends Toy> box 대상으로 넣는게 안된다고 이해하자!

 

c. 하한 제한된 와일드카드

하한 제한은 super로 한다.

extends와 반대로, Integer 와 부모만 올 수 있다.

Integer, Number, Object...

 

c-1. 하한 제한의 목적

이번엔 하한 제한으로 꺼내는 메소드에서 에러가 걸리고 있다.

 

d. 제한된 와일드카드와 오버로딩

만약 위의 예제에서 Toy와 아무 관련 없는 Snack클래스가 있다고 가정하자

매개변수로 Box<Snack>을 해당 메소드로 활용하고 싶은데 현재 메소드들은 Box<Toy> 인스턴스를 대상으로 정의된 메소드이다.

이를 오버로딩으로 해결할 수 있을까?

public static void outBox(Box<? extends Toy> box) {}

public static void outBox(Box<? extends Robot> box) {} 이런 형태의 오버로딩은 불가능하다

 

public static void inBox(Box<? super Toy> box, Toy n) {}

public static void inBox(Box<? super Robot> box, Robot n) {} 얘네는 두번째 매개변수로 인해 오버로딩 인정!

왜? type erasure 때문!! 컴파일러가 밑줄친 부분을 자기가 지운다.

그렇게 되면 위 두 문장은 같은 문장이 되어버려서 오버로딩이 안되는 것!

 

이런 불편함을 해결하기 위해...

d-1. 와일드카드 선언을 갖는 제네릭 메소드

public static void outBox(Box<? extends Toy> box){}

public static void outBox(Box<? extends Robot> box){} 이 문제의 두 문장을...

public static <T> void outBox(Box<? extends T> box){}

outBox는 Box<T>를 인자로 받고 꺼내는거만 가능하다는 거구나!(? extends)