지네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입체크를 해주는 기능이댜.
ArrayList의 경우 object[] 타입이라 다양한 종류의 객체를 담을 수 있지만 보통 한 종류의 객체를 담는 경우가 많다. 그런데 꺼낼때마다 형변환을 하고 타입체크하고... 너무 불편하다. 그리고 원하지 않는 종류의 객체가 포함되는걸 막을 방법도 없다.
지네릭스의 장점
1. 타입 안정성을 제공한다.
2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.
※ 기존에는 다양한 종류의 타입을 다루는 메서드의 매개변수나 리턴타입으로 Object타입의 참조변수를 많이 사용했고 그로 인해 형변환이 불가피 했지만 이젠 Object 대신 원하는 타입을 지정하기만 하면된다.
Box<String> b= new Box<String>();
b.setItem(new Object()); //에러 String타입 이외 지정불가
b.setItem("ABC");
String item=(String)b.getItem(); //**형변환 필요없음**
지네릭 타입에 Object타입을 지정하면 타입을 지정하지 않은게 아니고 일부로 알고 적은 것이므로 경고는 발생하지 않는다.
컴파일 후에 Box<String.> 과 Box<Integer.> 는 이들의 원시 타입 인 Box로 바뀐다. 즉 지네릭 타입이 제거 된다.
지네릭 클래스 Box의 객체를 생성할떄 객체별로 다른 타입을 지정하는 것은 적절하다. 하지만 static맴버에 타입변수T를 사용할 수 없다. T는 인스턴스로 간주 되기 떄문이다.(static맴버는 인스턴스변수를 참조할수 없다.)
Box<Apple>appleBox= new Box<Apple>();
BOX<Grape> grapeBox= new Box<Grape>();
지네릭 타입의 배열을 선언하는 것은 가능하지만 배열을 생성하는 것은 불가하다.
T[] itemArr // 가능
T[] tmpArr=new T[itemArr.length] //불가
->왜냐하면 new연산자 떄문이다. 이연산자는 컴파일시 T타입이 뭔지 정확히 알아야한다.
->instance of 연산자도 같은 이유로 T를 피연산자로 사용할수 없다.
참조변수와 생성자에 대입된 타입(매개변수화된 타입) 이 일치해야 한다
box<Apple> appleBox=new Box<Apple>(); //가능
두타입이 상속관계에 있어도 마찬가지이다. Apple이 Fruit의 자손이라고 가정하자.
box<Fruit> appleBox=new Box<Apple>(); //에러 대입된 타입 다름
두 지네릭 클래스의 타입이 상속관계에 있고 대입된 타입이 같은건 괜찮다.
Box<Apple> appleBox=new Fruit<Apple>(); //가능
add(T item) 대입된 타입과 다른 타입의 객체는 추가 할수 없다. 하지만 T가 fruit인 경우 Fruit 자손들은 매개변수가 될수 있다.
Box<Fruit> fruitBox=new Box<Fruit>();
fruitBox.add(new Fruit());
fruitBox.add(new Apple()); //자손 가능
'extends' 를 사용하면 특정 타입의 자손들만 대입할수 있다.
class FruitBox<T extends Fruit>{ //Fruit의 자손만 타입으로 올수 있다.
}
T타입에 Object 를 대입하면 모든 종류 의 객체를 저장할수 있다.
※ 만약 클래스가 아니라 인터페이스를 구현 해야 한다하면, 이떄도 'extends' 를 사용한다. implements 사용 x
※ 클래스 Fruit의 자손이면서 Eatable 인터페이스도 구현해야 한다면 '&' 기호를 써준다
->class FruitBox<T extends Fruit & Eatable>
1.쥬스를 만드는 메서드가 있다고 가정해보자.
Juice makeJuice(FruitBox<Fruit> box){
}
이렇게 FruitBox< Friut> box로 고정해 버리면 다른 타입의 객체FruitBox< Apple> box는 매개변수가 될수 없어서 매서드를 따로 만들어야한다.
3.그러나 지네락 타입이 다른 것만으로는 오버로딩이 성립하지 않는다.
이럴때 사용하는게 와일드카드 기호로는 '?'로 표현하고 어떠한 타입도 될수 있다.
< ? extends T> = 와일드 카드의 상한 제한/ T와 그 자손들만 가능
< ? super T> = 와일드 카드의 하한 제한 /T와 그 조상들만 가능
< ?> = 제한없음/ 모든타입가능