다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스를 컴파일 할 때, 타입을 체크해주는 기능
=> 객체들의 타입 안정성과 형변환의 번거로움이 줄어드는 기대를 할 수 있다.
class Box<T>{
T item;
void setItem(T item){
this.item = item;
}
T getItem(){
return item;
}
}
T
는 타입변수이다. T
라는 변수에 여러 타입들이 들어갈 수 있는것이다. T
가 Integer
,String
,Objcet
등 여러 타입이 된다.
Box<String> stringBox = new Box<String>;
// T라는 타입변수에 String타입을 지정하였다
Box<Integer> integerBox = new Box<Integer>;
// T라는 타입변수에 Integer타입을 지정하였다
class Box<T>{
//static T item; ERROR --1
T[] itemArr;
T[] toArray(){
// T[] tmpArr = new T[itemArr.length]; ERROR --2
}
}
당연한 얘기겠지만, static
멤버는 제네릭 클래스에 존재할 수 없다(--1)
. 타입변수가 존재하기 때문에 클래스변수가 존재하면 다른 타입으로 저장될 수 있기 때문이다.
--2
를 보면 제네렉배열을 생성하는 단계에서 에러가 난다. new
라는 연산자는 T(타입)에 대해 정확히 알고 있어야 하기 때문이다. 위 예시처럼 배열 뿐만아니라, T
객체 생성도 불가하다. 굳이 사용하고자 한다면, newInstance()
라는 API
를 사용할 수 있다.
class Box<T extends Fruit>{
ArrayList<T> list = new ArrayList<>(); //--1
}
extends
를 사용하면, T
라는 타입변수는 Fruit
타입과 그 자손들만 대입이 가능하도록 제한을 둘 수 있다.
--1
의 list
에는 Fruit
와 자손관계인 Apple
,Grape
와 같은 타입들만 저장될 수 있도록 제한이 되었다.
제네릭 타입간의 다형성을 부여할 수 있다.
<? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
<? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
<?> : 모든 타입이 가능 (<? extends Object>와 동일)
예를 들어,
class Parent{}
class Child extends Parent{}
class GrandChild extends Parent{}
public class playGround{
public static void play(){
// ArrayList<Parent> parentList = new ArrayList<Child>;
ArrayList<? extends Parent> parentList = new ArrayList<Parent>;
parentList = new ArrayList<GrandChild>;
}
}
실용적인 예시는 아니지만, 와일드카드를 통해 제네릭 타입간의 다형성을 사용할 수 있다.