다중 매개변수 기반 제네릭 클래스의 정의하기
class DBox<L, R> {
private L left; // 왼쪽 수납 공간
private R right; // 오른쪽 수납 공간
public void set(L o, R r) {
left = o;
right = r;
}
@Override
public String toString() {
return left + " & " + right;
}
}
public static void main(String[] args) {
DBox<String, Integer> box = new DBox<String, Integer>();
box.set("Apple", 25);
System.out.println(box); // => Apple & 25 출력!
}
DBox 클래스에 제네릭을 <String, Integer>로 설정했으므로 L => String, R => Integer가 된다.
타입 매개변수의 이름 규칙은?
=> 이름은 한 문자이고 대문자로 작성하는 것이 관례이다
보편적인 선택
E | Element |
K | Key |
N | Number |
T | Type |
V | Value |
기본 자료형에 대한 제한 => Wrapper 클래스 사용하기
Box<int> box = new Box<int>();
=> 타입 인자로 기본 자료형이 올 수 없으므로 컴파일 오류 발생하므로 아래와 같이 생성 가능
Box<Integer> box = new Box<>();
// 다이아몬드 기호!!
// 생성할 때 타입은 생략 가능!
// => 참조 변수 선언을 통해서 컴파일러가 타입을 유추함!
제네릭 클래스의 타입 인자 제한하기
class Box<T extends 클래스명 혹은 인터페이스명> {...}
- <T> : 어떤 타입 파라미터든 허용
- <T extends 클래스 또는 인터페이스> : 부모 타입을 상속받은 자식 클래스만 허용
- <T extends 클래스A> : 클래스A, 또는 클래스A의 상속받은 클래스만 허용
=> 클래스 하나만 작성 가능하고 final로 선언되지 않은 클래스이어야 함
=> final로 선언된 클래스는 다른 클래스가 상속 받을 수 없기 때문이다 - <T extends 인터페이스A> : 인터페이스A를 구현(상속)한 클래스만 허용(인터페이스 여러개 작성 가능함)
- <T extends 클래스A> : 클래스A, 또는 클래스A의 상속받은 클래스만 허용
- <T extends 클래스A & 인터페이스A> : 클래스A를 상속받고 인터페이스A를 구현한 클래스만 허용
=> 제네릭 타입에 extends 키워드를 사용하여 클래스일 경우 T가 해당 클래스를 상속하고 있는 타입으로 제한한다. 인터페이스일 경우 T가 해당 인터페이스를 구현하고 있는 타입으로 제한한다.
(클래스일 경우 해당 클래스도 포함됨)
class Box<T extends Number> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
public static void main(String[] args) {
Box<Integer> iBox = new Box<>();
iBox.set(24);
Box<Double> dBox = new Box<>();
dBox.set(5.97);
. . . .
}
extends 상속 키워드를 사용하여 T가 Number클래스이거나 Number를 상속받지 않는 클래스일 경우 에러를 발생시킨다
제네릭 클래스의 타입 인자를 인터페이스로 제한하기
interface Eatable { public String eat(); } // abstract 생략됨
class Apple implements Eatable { // Apple 클래스가 Eatable 인터페이스를 구현함
public String eat() {
return "It tastes so good!";
}
. . . .
}
class Box<T extends Eatable> {
T ob;
public void set(T o) { ob = o; }
public T get() {
System.out.println(ob.eat()); // Eatable로 제한하였기에 eat 호출 가능
return ob;
}
}
=> T extends Eatable의 의미는 제네릭을 설정해서 넘겨받는 타입이 되는 클래스가 Eatable 인터페이스를 구현하고 있지 않을 경우 타입에러 발생!!
하나의 클래스와 하나의 인터페이스에 대해 동시 제한
class Box<T extends Number & Eatable> {...}
인터페이스와 클래스를 동시에 지정할 수도 있다.
참조
[JAVA] The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended
The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended유형 매개변수 T는 최종 유형 Integer에 의해 제한되어서는 안 됩니다. 최종 유형은 더 이상 확장할
seong-jun.tistory.com
'Java' 카테고리의 다른 글
[JAVA] 자바 - 무엇이든 담을 수 있는 제네릭(Generic) 프로그래밍 (0) | 2025.02.20 |
---|---|
[JAVA] The type parameter T should not be bounded by the final type Integer. Final types cannot be further extended (0) | 2025.02.20 |
[JAVA] File클래스 (0) | 2025.02.18 |
[JAVA] 자바 OutputStream(바이트 단위 스트림) (0) | 2025.02.17 |
[JAVA] 자바 InputStream(바이트 단위 스트림) (0) | 2025.02.17 |