为什么java.lang.Class的getInterfaces()方法返回Class <! - ? - > []而不是Class <! - ?超级T - > []?

时间:2011-11-18 22:48:24

标签: java generics interface bounded-wildcard

(为了澄清问题,'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>才能获得正确的类型。编译器警告可以被抑制,但它是否合理?是否有某种情况下这种演员不是真的?

2 个答案:

答案 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

它帮助了我。也可以帮助你:))