列表初始化时出现奇怪的错误

Jor*_*pos 10 java generics

我的一个朋友问我是否可以帮助他找出错误背后的原因,他正在编写一段代码,最重要的是当他添加一些代码时错误消失的原因.我查看了有关课程的文档,但也找不到原因.

这是代码:

import java.util.Arrays;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public class Test {

    public static void main(String[] args) {
        /**
        * This line shows this compilation error in eclipse:
        * Type mismatch: cannot convert from 
        *     List<Class<? extends JComponent&Accessible>> 
        *          to List<Class<? extends JComponent>>
        */
        List<Class<? extends JComponent>> listComp = Arrays.asList(JTabbedPane.class, 
                                                                   JPanel.class);

        /**
        * This one compiles fine and the difference is that
        * he added JComponent.class on the list and the 
        * code is working fine
        */
        List<Class<? extends JComponent>> listComp2 = Arrays.asList(JTabbedPane.class, 
                                                                    JPanel.class, 
                                                                    JComponent.class);
    }

}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,唯一的区别是,在第二个列表变量中,我们添加了JComponent.class并且错误消失了.

这是为什么?

更新

我们正在使用Java JDK 7 update 80

更新2

另一位朋友建议使用这段代码,它也有效:

List<Class<? extends JComponent>> listComp = 
      new ArrayList<Class<? extends JComponent>> ( Arrays.asList( JTabbedPane.class, 
                                                                  JPanel.class));
Run Code Online (Sandbox Code Playgroud)

rge*_*man 8

我可以在Java 7中复制此问题,但是当我切换到Java 8时,不再给出错误.另外,如果我留在Java 7中,但是我给出了一个类型参数Arrays.asList,则不再给出错误.

List<Class<? extends JComponent>> listComp =
    Arrays.<Class<? extends JComponent>>asList(JTabbedPane.class, JPanel.class);
Run Code Online (Sandbox Code Playgroud)

Java将尝试确定返回的目标类型Arrays.asList.显然,无论是JTabbedPaneJPanel扩展JComponent和实现Accessible.但是,JComponent没有实施Accessible.结果是编译器可以从所有类型中获得的最完整,特定的类型.对于您的第一个示例,推断类型是List<Class<? extends JComponent & Accessible>>,因为两个参数都适合该类型.添加时JComponent,推断类型现在List<Class<? extends JComponent>>和匹配listComp,允许它在Java 7中编译.

Java 8具有改进的目标类型推断功能.该教程的示例是Collections.emptyList传递给需要的方法List<String>.在Java 7中,推断类型将是,List<Object>并且将发生编译错误.但是,在Java 8中,推断类型是List<String>匹配方法的参数,并且代码编译.

这与您的代码的示例并不完全相同,但它足够接近我认为通常,Java 8改进的目标类型推断解释了代码编译该版本的原因.