我的一个朋友问我是否可以帮助他找出他在一段代码中出现错误的原因,最重要的是为什么当他添加一些代码时,错误消失了.我已经查看了关于课程的文档,也找不到原因.
这是代码:
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); } }
正如你所看到的,唯一的区别是在第二个列表变量中,我们添加了JComponent.class,错误消失了.
这是为什么?
更新
我们正在使用Java JDK 7更新80
更新2
另一位朋友建议这段代码,它也有效:
List<Class<? extends JComponent>> listComp = new ArrayList<Class<? extends JComponent>> ( Arrays.asList( JTabbedPane.class,JPanel.class));
解决方法
我可以在Java 7中复制这个问题,但是当我切换到Java 8时,不再给出错误.另外,如果我留在Java 7,但是我给一个类型参数Arrays.asList,错误不再给出.
List<Class<? extends JComponent>> listComp = Arrays.<Class<? extends JComponent>>asList(JTabbedPane.class,JPanel.class);
Java将尝试确定Arrays.asList返回的目标类型.显然,JTabbedPane和JPanel都扩展了JComponent并实现了Accessible.但是,JComponent不实现Accessible.结果是编译器可以从所有类型获得的最完整的特定类型.对于您的第一个例子,推断的类型是List< Class<?扩展JComponent&可访问>>因为两个参数都适合该类型.当您添加JComponent时,推断的类型现在为List< Class<?扩展JComponent>>并且匹配listComp,允许它在Java 7中编译.
Java 8功能改进了target type inference.该教程的示例是将Collections.emptyList传递给需要List< String>的方法.在Java 7中,推断的类型将是List< Object>并发生编译错误.然而,在Java 8中,推断的类型是List< String>,匹配该方法的参数和代码编译.
这与您的代码不是一样的例子,但是它足够接近,我相信通常来说,Java 8的改进的目标类型推断解释了代码为什么编译与该版本.