제네릭 타입 범위 제한
제네릭 타입 범위 제한의 필요성
다양한 타입을 처리할 수 있다는 장접이 있지만 어떤 타입으로 올지 모르기 때문에 Object 클래스의 메서드 외에는 사용할 수 있는 메서드가 제한적이다.
class A {
<T> void example(T t) {
// t.length() 사용 불가능
}
<T extends String> void example2(T t) {
// 제한을 함으로써 사용 가능
t.length();
}
}
제네릭 클래스의 타입 제한
class 클래스명 <T extends 최상위 클래스 / 인터페이스명> {
}
class Fruit {
}
class Apple extends Fruit{
}
class Pencil {
}
// 과일로 타입으로 제한
class Goods<T extends Fruit> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
public class Test {
public static void main(String[] args) {
Goods<Fruit> fruitGoods = new Goods<>();
// 과일 타입은 가능
fruitGoods.set(new Apple());
// fruitGoods.set(new Pencil()); 아닌 경우 불가능
}
}
제네릭 메서드의 타입 제한
public <T extends 최상위 클래스 / 인터페이스명> T example(T t) {
// ...
}
// 클래스로 제한
class A {
<T extends String> void method(T t) {
System.out.println(t.length());
}
}
// 인터페이스로 제한
interface MyInterface {
void print();
}
class B {
// 인터페이스에서도 extends 키워드를 사용한다.
<T extends MyInterface> void example(T t) {
t.print();
}
}
메서드 매개변수일 때 제네릭 클래스의 타입 제한
// 상속 구조: A <- B <- C <- D
class A {}
class B extends A {}
class C extends B {}
class D extends C {}
class Goods<T> {
private T t;
public T get() {
return t;
}
public void set(T t) {
this.t = t;
}
}
class Test {
void mehod1(Goods<A> g) {} // A인 객체만 가능
void mehod2(Goods<?> g) {} // 모든 타입 객체 가능
void mehod3(Goods<? extends B> g) {} // B 또는 B의 자식 클래스인 객체만 가능
void mehod4(Goods<? super B> g) {} // B 또는 B의 부모 클래스인 객체만 가능
}
public class Test3 {
public static void main(String[] args) {
Test t = new Test();
// case1
t.mehod1(new Goods<A>());
// t.mehod1(new Goods<B>());
// t.mehod1(new Goods<C>());
// t.mehod1(new Goods<D>());
// case2
t.mehod2(new Goods<A>());
t.mehod2(new Goods<B>());
t.mehod2(new Goods<C>());
t.mehod2(new Goods<D>());
// case3
// t.mehod3(new Goods<A>());
t.mehod3(new Goods<B>());
t.mehod3(new Goods<C>());
t.mehod3(new Goods<D>());
// case4
t.mehod4(new Goods<A>());
t.mehod4(new Goods<B>());
// t.mehod4(new Goods<C>());
// t.mehod4(new Goods<D>());
}
}
댓글남기기