여러 클래스를 가진 Java Generics 와일드 카드


385

Class 객체를 갖고 싶지만 클래스 A를 확장하고 인터페이스 B를 구현하도록 클래스를 강제로 설정하고 싶습니다.

내가 할 수있는:

Class<? extends ClassA>

또는:

Class<? extends InterfaceB>

하지만 둘 다 할 수는 없습니다. 이것을 할 수있는 방법이 있습니까?

답변:


613

실제로 원하는 것을 할 수 있습니다 . 여러 인터페이스 또는 클래스와 인터페이스를 제공하려면 와일드 카드를 다음과 같이 보여야합니다.

<T extends ClassA & InterfaceB>

페이지 하단의 sun.com 의 Generics Tutorial , 특히 Bounded Type Parameters 섹션을 참조하십시오. 원하는 & InterfaceName각 인터페이스를 사용하여 원하는 경우 실제로 둘 이상의 인터페이스를 나열 할 수 있습니다 .

이것은 임의로 복잡해질 수 있습니다. 시연하려면 다음의 JavaDoc 선언을 참조하십시오 Collections#max.

public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)

왜 그렇게 복잡한가? Java Generics FAQ : 바이너리 호환성 유지 .

변수 선언에서는 작동하지 않는 것처럼 보이지만 클래스에 일반적인 경계를 설정하면 작동합니다. 따라서 원하는 작업을 수행하려면 몇 개의 농구대를 뛰어 넘어야 할 수도 있습니다. 그러나 당신은 할 수 있습니다. 클래스에 일반적인 경계를두고 다음과 같이 할 수 있습니다.

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}

얻을 variable것을 당신이 원하는 것을 제한이있다. 자세한 정보 및 예 는 Java 5.0Generics 3 페이지를 참조하십시오 . 참고에 <T extends B & C>, 클래스 이름이 먼저 와야하고, 인터페이스은 다음과 같습니다. 물론 단일 클래스 만 나열 할 수 있습니다.


94
도움이됩니다. 클래스가 먼저 와야 한다고 언급 할 가치가 있습니다. '<T는 InterfaceB & ClassA를 확장합니다.'라고 말할 수 없습니다.
EricS

5
클래스를 확장하거나 인터페이스를 구현 해야하는 T에 대해 어떻게 동일합니까?
Ragunath Jawahar

1
@RagunathJawahar : 이것에 대해 너무 개방적 일 수는 없습니다. 경계가 있어야하며 그 중 하나는 인터페이스가있는 곳과 클래스가있는 곳 및 상속을 사용하는 방법을 미리 알고 있습니다. 클래스 또는 인터페이스가 될 경우 유형 매개 변수를 알아야합니다.
Eddie

4
답의 첫 번째 줄은 "와일드 카드가 다음과 같이 보이도록"말합니다. 더 없다 ?그래서 정말 "와일드 카드"입니다, 그 표현에? 타입 매개 변수가 실제로 와일드 카드 일 때 전체 "한 번에 두 가지를 연장"개념을 사용할 수 없기 때문에 묻습니다.
The111

1
예, 실제로 와일드 카드가 아니며 OP에서 와일드 카드로 요청한 내용을 수행 할 수 없습니다. 와일드 카드가 아니라 OP가 원하는 것을 효과적으로 수행 있습니다 .
Eddie

17

"익명"유형 매개 변수 (예 :)를 사용하는 와일드 카드로 ?수행 할 수 없지만 "명명 된"유형 매개 변수로 수행 할 수 있습니다. 메서드 또는 클래스 수준에서 형식 매개 변수를 선언하면됩니다.

import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}

2
와일드 카드가 허용되지 않는 이유는 무엇입니까? 즉, 왜 이것이 유효하지 않아야하는지 알 수 없습니다. ArrayList <? ClassA & InterfaceB> 목록을 확장합니다. 그런 다음 목록에서 요소를 가져 오면 ClassA 또는 InterfaceB 유형의 변수에 할당 할 수 있습니다.
Mark

와일드 카드를 변수로 바꾸는 것은 훌륭한 기술입니다! 그러나 항상 작동하지는 않습니다. 예를 들어, Java는 주석 값 유형에 이름 유형 변수를 허용하지 않지만 와일드 카드를 허용합니다.
sigpwned
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.