(To clear up the question, 'T' refers to a type parameter declared in Class)
Just as an example, please review the following application:
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());
}
}
}
The output is what one would expect:
TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC
So, based on this example above, we can see that the compiler recognizes that InterfaceA does meet the bounds of the wildcard , as do all of the other interfaces.
Intuitively, I would expect the following to be safe, but it is not:
Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();
The compiler gives a warning, because the signature says that it returns Class; however, the javadoc for Class states the following:
If this object represents a class, the return value is an array containing objects representing all interfaces implemented by the class.
'This object' refers in our case to ClassA
. Based on this statement, if we call:
ClassA.class.getInterfaces()
then we know, logically, that every Class<?>
in the returned array will contain a reference to a super type of ClassA
.
As an additional point of reference:
From the Java Language Reference, Third Edition:
A class necessarily implements all the interfaces that its direct superclasses and direct superinterfaces do. This (multiple) interface inheritance allows objects to support (multiple) common behaviors without sharing any implementation.
Reading this and other parts of the specification, I would think that any class or interface implemented or exteneded by a class T
would fall into the bounds <? super T>
.
EDITED:
It has been suggested that there is no concrete reason for my question. I will provide an example:
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 }
The problem is at line 15. You have to cast to <? super W>
to get the correct type. The compiler warning can be suppressed, but is it justified? Is there some scenario where this cast is not true?
Class<? super T>
. This being the case, it seems even more appropriate for getInterfaces() to return similarly to me. If they were thinking, as you suggest, that Class would never use any of those methods accessible by allowing the bounded wildcard, why would Class provide a superclass being specified as<? super T>
? – Flatfoot