13

(为了澄清问题,“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确实满足 wildcard 的边界,所有其他接口也是如此。

直觉上,我希望以下内容是安全的,但事实并非如此:

Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();

编译器发出警告,因为签名说它返回 Class;但是,Class 的 javadoc 声明如下:

如果此对象表示一个类,则返回值是一个数组,其中包含表示该类实现的所有接口的对象。

在我们的例子中,“这个对象”指的是ClassA。基于此声明,如果我们调用:

ClassA.class.getInterfaces()

那么我们从逻辑上知道,Class<?>返回数组中的每个都将包含对超类型的引用ClassA

作为一个额外的参考点:

来自 Java 语言参考,第三版:

一个类必须实现其直接超类和直接超接口所做的所有接口。这种(多个)接口继承允许对象在不共享任何实现的情况下支持(多个)公共行为。

阅读规范的这个部分和其他部分,我认为任何由类实现或扩展的类或接口T都会落入 bounds <? 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>才能获得正确的类型。编译器警告可以被抑制,但它是否合理?是否存在这种演员表不正确的情况?

4

2 回答 2

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>

于 2011-11-18T23:43:11.443 回答
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), 但 NOT add(aString)。好吧,String 是一个对象,所以add(aString)仍然可以编译。

复制自:堆栈溢出 - 使用“超级”关键字绑定泛型

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

于 2018-01-29T13:18:53.187 回答