(为了澄清问题,'T'指的是在Class中声明的类型参数)
举个例子,请查看以下申请表:
public class TestClass {
interface InterfaceA{}
interface InterfaceB{}
interface InterfaceC{}
class ClassA implements InterfaceA, InterfaceB, InterfaceC{}
public static void main(String[] args){
Class<? super ClassA> superClass1 = ClassA.class;
Class<? super ClassA> superclass2 = InterfaceA.class;
Class<? super ClassA> superclass3 = InterfaceB.class;
Class<? super ClassA> superclass4 = InterfaceC.class;
for(Class<?> clazz : ClassA.class.getInterfaces()){
System.out.println(clazz.getName());
}
}
}
输出是人们所期望的:
TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC
因此,基于上面的这个例子,我们可以看到编译器认识到InterfaceA 符合通配符的边界,所有其他接口也是如此。
直观地说,我希望以下内容是安全的,但不是:
Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();
编译器发出警告,因为签名表示它返回Class;但是,Class的javadoc声明如下:
如果此对象表示类,则返回值为数组 包含表示由实现的所有接口的对象 类。
'此对象'在我们的案例中指的是ClassA
。基于这个陈述,如果我们打电话:
ClassA.class.getInterfaces()
然后我们从逻辑上知道,返回数组中的每个Class<?>
都将包含对超类型ClassA
的引用。
作为额外的参考点:
来自Java语言参考,第三版:
一个类必然实现其直接的所有接口 超类和直接超接口。这个(多个)接口 继承允许对象支持(多个)常见行为 没有共享任何实现。
阅读本规范的其他部分,我认为类T
实现或扩展的任何类或接口都属于<? super T>
的范围。
编辑:
有人提出我的问题没有具体原因。我将举一个例子:
1 import java.util.Map;
2 import java.util.HashMap;
3
4 public class MapWrapper<T> {
5 private final Map<Class<?>, OtherClass<T,?>> map = new HashMap <Class<?>, OtherClass<T,?>>();
6
7 public <W> void addToMap(Class<W> type, OtherClass<T,? super W> otherClass){
8 map.put(type, otherClass);
9 }
10
11 public <W> OtherClass<T,? super W> getOtherClassForAnyInterface(Class<W> type){
12 if(type.getInterfaces()!=null){
13 for(Class<?> interfaceType : type.getInterfaces()){
14 // Here, a cast is necessary. It throws a compiler warning for unchecked operations (rightfully so)
15 OtherClass<T,? super W> otherClass = (OtherClass<T,? super W>)getOtherClassForInterface(interfaceType);
16 if(null!=otherClass){
17 return otherClass;
18 }
19 }
20 }
21 return null;
22 }
23
24
25 public class OtherClass<T,V> {}
26
27 }
问题出在第15行。您必须强制转换为<? super W>
才能获得正确的类型。编译器警告可以被抑制,但它是否合理?是否有某种情况下这种演员不是真的?
答案 0 :(得分:5)
你是对的,返回类型可能更具体。
但是,Class<? super X>
无论如何都不是很有用。 Class<?>
足以满足大多数用途。
如果我们有G<T>
声明,G<? super X>
有用,通常G
应该有接受T
的方法。例如,List<T>
有add(T)
。因此List<? super X>
很有用,我们可以在其上调用add(x)
(x
类型为X
)
Class
没有这样的方法。
您是否有一个令人信服的用例,您确实需要Class<? super ClassA>
?
答案 1 :(得分:0)
再次,让我们说你有这个通用的方法声明:
<T super Integer> void add(T number) // hypothetical! currently illegal in Java
你有这些变量声明:
Integer anInteger
Number aNumber
Object anObject
String aString
您对<T super Integer>
的意图(如果它是合法的)是它应该允许add(anInteger)
和add(aNumber)
,当然还有add(anObject)
,但不是{ {1}}。好吧,String是一个Object,所以add(aString)
仍然可以编译。
复制自:Stack Overflow - Bounding generics with 'super' keyword
它帮助了我。也可以帮助你:))