extends
로 대입할 수 있는 타입을 제한예)
class FruitBox<T extends Fruit> { ArrayList<T> list = new ArrayList<T>(); ... }
<T extends Fruit>
: Fruit
클래스 포함 자손만 대입 가능FruitBox<Apple> appleBox = new FruitBox<Apple>(); //(O) FruitBox<Toy> toyBox = new FruitBox<Toy>(); //(X) Toy는 Fruit의 자손이 아니기에
extends
사용예)
interface Eatable {} class FruitBox<T extends Eatable> {...}
<T extends Eatable>
: Eatable
인터페이스를 구현한 클래스만 대입 가능ex12_03
import java.util.ArrayList;
public class Ex12_03 {
public static void main(String[] args) {
FruitBox<Fruit> fBox = new FruitBox<>();
FruitBox<Apple> aBox = new FruitBox<>();
FruitBox<Grape> gBox = new FruitBox<>();
// FruitBox<Grape> gBox = new FruitBox<Apple>(); //타입불일치
// FruitBox<Fruit> gBox = new FruitBox<Apple>(); //타입불일치
// FruitBox<Toy> tBox = new FruitBox<>(); //Toy는 FruitBox의 타입변수에 못들어감
fBox.add(new Fruit());
fBox.add(new Apple()); //다형성O
fBox.add(new Grape());
aBox.add(new Apple());
// aBox.add(new Fruit());
// aBox.add(new Grape());
gBox.add(new Grape());
// gBox.add(new Fruit());
// gBox.add(new Apple());
System.out.println(fBox.size());
System.out.println(fBox);
for(int i=0; i<fBox.size(); i++) {
System.out.println(fBox.get(i));
}
System.out.println(aBox.size());
System.out.println(aBox);
for(int i=0; i<aBox.size(); i++) {
System.out.println(aBox.get(i));
}
System.out.println(gBox.size());
System.out.println(gBox);
for(int i=0; i<gBox.size(); i++) {
System.out.println(gBox.get(i));
}
}
}
interface Eatable {}
class Fruit implements Eatable{
public String toString() { return "맛있는Fruit"; }
}
class Apple extends Fruit{
public String toString() { return "아침엔Apple"; }
}
class Grape extends Fruit{
public String toString() { return "달디단Grape"; }
}
class Toy {
public String toString() { return "Toy"; }
}
class Box<T>{
ArrayList<T> list = new ArrayList<>();
void add(T item) { list.add(item);}
T get(int i) { return list.get(i);}
int size() { return list.size();}
public String toString() { return list.toString();}
}
class FruitBox<T extends Fruit & Eatable> extends Box<T>{}
//타입변수: Fruit클래스를 상속받고(본인 또는 자손이고) Eatable인페를 구현한 클래스
//**따로 쓰지않고 &로 같이 함!!
//사실 여기서 Fruit가 Eatable을 구현하기에 (& Eatable)을 안써도 된다.
//Box<T>를 상속받음
3
[맛있는Fruit, 아침엔Apple, 달디단Grape]
맛있는Fruit
아침엔Apple
달디단Grape
1
[아침엔Apple]
아침엔Apple
1
[달디단Grape]
달디단Grape
static멤버
는 모든 인스턴스에 공통이니까!!더 자세히 말하면,
static은 인스턴스 생성과 별도로 선언순간 메모리에 올라가 있다. 그런데 그런 static으로 선언된 메소드에 인스턴스가 생성되는 시점에 결정되는 제네릭 타입을 매개변수로 받을 수는 없을 것이다. - by.지네릭vs.와일드카드
class Box<T>{
static T item; //(X)에러
static int compare(T t1, T t2) {...} //(X)에러
}
class Box<T>{
T[] itemArr; //(O) T타입의 배열을 위한 참조변수
...
T[] toArray() {
T[] tmpArr = new T[itemArr.length];
//(X)에러. 지네릭 배열 생성 불가!!!!!
new
+ 다음엔 확정된 타입이 와야 하니까!!new T()
, new T[]
❌