为什么java.lang.Class的getInterfaces()方法返回Class<?>[]而不是Class<?超级T>[]?非数组示例

2022-09-04 23:05:08

(为了澄清这个问题,“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;但是,类的 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>


答案 1

你是对的,返回类型可以更具体。

但是,无论如何都不是很有用。 对于大多数用法来说就足够了。Class<? super X>Class<?>

如果我们有一个声明,为了有用,通常应该有接受的方法。例如,具有 .所以是有用的,我们可以调用它(类型G<T>G<? super X>GTList<T>add(T)List<? super X>add(x)xX)

Class没有这样的方法。

您是否有真正需要的令人信服的用例?Class<? super ClassA>


答案 2

同样,假设您有这个泛型方法声明:

非数组示例

<T super Integer> void add(T number) // hypothetical! currently illegal in Java

你有这些变量声明:

Integer anInteger Number aNumber Object anObject String aString

你的意图(如果它是合法的)是它应该允许,和,当然,但不是。好吧,String是一个对象,所以无论如何都会编译。<T super Integer>add(anInteger)add(aNumber)add(anObject)add(aString)add(aString)

复制自 : 堆栈溢出 - 使用“super”关键字限定泛型

它帮助了我。可能会帮助你太:)