我发现在Eclipse (使用Eclipse编译器)中,我可以使用一些Java 7语言特性,但仍然可以创建Java 6类文件。在下面的图像中,您可以看到成功编译为Java 6类文件的两个Java 7语言特性。但是,那些注释掉的其他Java 7特性并不编译。
我的假设是,Eclipse正在确定哪些Java 7语言特性与Java 6 JVM兼容,哪些不兼容。例如,泛型类型JComboBox只是一个编译(而不是运行时)特性,所以我可以想象它是如何兼容的。虽然我认为开关字符串特性可能会造成字节代码的差异,并依赖于新的JVM特性,但我可能错了……
我的问题:
为了便于比较,这里是切换到Java 6编译器时的结果,正如预期的那样。
发布于 2014-10-30 15:47:11
我想有两件事正在发生:
JComboBox
)是因为Java1.7 rt.jar
是链接的,而不是Java1.6 rt.jar
(我有一个用JavaSE-1.6安装的项目,在这种情况下,即使使用第一个设置组合,第一行也不会编译)。但这是类库问题,而不是语言版本问题。(与运行javac
时相比,如果您使用较新的rt.jar
编译Java应用程序,即使使用Java也会遇到很多问题)。因此,简而言之,您已经在(可能)不同寻常的Eclipse配置中发现了至少一个bug。小心,不要依赖它。
发布于 2014-10-30 17:37:14
我不知道Eclipse为什么允许这样做,或者这是否只是一个bug。1.7 javac
会告诉你
error: strings in switch are not supported in -source 1.6
我也不知道为什么JComboBox
能工作,
System.out.println(new JComboBox<String>() {}.getClass().getGenericSuperclass());
> javax.swing.JComboBox<java.lang.String>
在运行时具有不应该存在的通用信息。允许对非泛型类使用泛型,则应以不兼容为由拒绝IMO。不过,我并没有在JVM6上运行以上的代码。也许它甚至会坠毁。
但至少从技术上讲,switch
是没有问题的。http://www.benf.org/other/cfr/java7switchonstring.html显示,这只是一个不需要新的语言特性、API或字节码的编译器技巧。
略为简化的例子:
int java7(String string) {
switch (string) {
case "BB":
return 12;
case "FRED":
return 13;
}
return 0;
}
从本质上
int java6(String string) {
switch (string.hashCode()) {
case 2112:
if (string.equals("BB"))
return 12;
break;
case 2166379:
if (string.equals("FRED"))
return 13;
break;
}
return 0;
}
这是基于这样一个事实,即String#hashCode()
的结果是指定的,不能更改。编译器只会为您节省一些时间,以便更快地编写其他法律代码。
同样的情况也应该适用于菱形操作符:例如,new ArrayList<>()
可以简单地由编译器解析。
android工具,允许相同的半7兼容性,允许你使用它。然而,不同之处在于,它们使用的是针对Java 7的.class文件。安卓需要将.class文件转换成它的内部格式,这样他们的.class到.dex编译器就可以使用任何输入来生成被安卓运行时理解的指令。
例如,使用资源的尝试就无法工作,因为它需要Java6中不存在的AutoCloseable
接口。
像Lambda表达式这样的特殊特性也需要新类型的字节码。
发布于 2014-10-30 15:23:33
我猜你是正确的,为什么当设置为Java 6时,ECJ会编译一些东西而不是其他东西。泛型只会编译到与强制转换相同的东西,所以如果目标设置为java 6,这可能就是它工作的原因?
有关javac和ECJ之间的其他差异,请参见What is the difference between javac and the Eclipse compiler?。
https://stackoverflow.com/questions/26656774
复制相似问题