是否可以实现具有签名List <Class <?的方法?在Java中扩展Annotation >>

Ada*_*ker 5 java generics wildcard

问题在于一般限制:

public List<Class<? extends Annotation>> getAnnotations() {
    return new ArrayList<>(Arrays.asList(Override.class));
}
Run Code Online (Sandbox Code Playgroud)

实际返回类型是ArrayList<Class<Override>>
Method期望的List<Class<? extends Annotation>>

Class<Override>Class<? extends Annotation>
Class<? extends Annotation> c = Override.class;//允许的子类型

ArrayListList如果元素的类型匹配:
List<? extends Number> l = new ArrayList<Integer>();//允许,则是a的子类型

但是,这是不允许的:

List<Class<? extends Annotation>> l = Arrays.asList(Override.class);
List<Class<? extends Annotation>> l = new ArrayList<>(Arrays.asList(Override.class));
Run Code Online (Sandbox Code Playgroud)

甚至是可能还是Class通配符被破坏了?

Kon*_*kov 2

我认为这是因为 jdk 1.7 类型推断性质。

您可能已经知道,该Arrays.asList(T ... elems)方法是通用的,但我们很少显式指定我们希望该方法使用的类型参数,因此我们依赖于编译器的类型推断功能。

因此,当编译器看到一条Arrays.asList(Override.class)语句时,它会推断该方法的类型参数应该替换为Class<Override>,即我们将拥有以下形式的方法版本:

public List<Class<Override>> asList(Class<Override> ... elems)
Run Code Online (Sandbox Code Playgroud)

但是,如果您将该方法的类型参数显式设置为

List<Class<? extends Annotation>> l = 
               Arrays.<Class<? extends Annotation>>asList(Override.class);
Run Code Online (Sandbox Code Playgroud)

那么编译器实际上会知道类型参数必须替换为什么,然后该方法的版本.asList()将是:

public List<? extends Annotation> asList(Class<? extends Annotation> ... elems)
Run Code Online (Sandbox Code Playgroud)

现在这可以很好地编译,因为Class<? extends Annotation>Class<Override>. 在 Java8 中,类型推断功能得到了进一步改进,因此您不必显式设置方法的类型参数.asList()

然而,有趣的问题是

为什么List<Class<Override>>不兼容List<Class<? extends Annotation>>

java.lang.Class是一个final,这将有助于回答以下两个问题,这两个问题的组合将回答上述问题。:)

所以,

  • 是什么List<Class<Override>>意思?

List<Class<Override>>意味着我们只能Class<Override>向列表中添加 的实例,而不能添加任何其他内容。这很棒,因为我们知道我们甚至不能添加Class<Override>子类,因为Class类型是final.

  • 是什么List<Class<? extends Annotation>>意思?

这种类型List代表了一整套列表,所有类列表都是该Annotation类型的子类,这意味着我们可以成功地将任何注释类型(例如,SuppressWarnings.classOverride.classDocumented.class等)添加到列表中。

让我们假设以下示例实际上是正确的:

List<Class<Override>> overrides = Arrays.asList(Override.class);
List<Class<? extends Annotation>> annotations = new ArrayList<>();
annotations = overrides;
annotations.add(SuppressWarnings.class); //HUGE PROBLEM
annotations.add(Documented.class); //ANOTHER HUGE PROBLEM
Run Code Online (Sandbox Code Playgroud)

两个巨大的问题来自于我们试图Override向 中添加一些非实例overrides,这是非常错误的。

我们有足够智能的编译器,它实际上可以检测到此类可能的问题,并且抛出编译时错误是阻止我们这样做的方法。

更多信息: