你能用Java 8编译一个类,然后在Java 7中使用它吗?
你能用Java 8编译一个类,然后在Java 7中使用它吗?
我想写一个具有简单接口(与Java 7兼容)的实用程序JAR,但在内部到处使用lambdas。然后我想在一些必须用JDK 7编译的代码中使用该实用程序。
可能吗?
如您所见,有一些相互矛盾的答案。那么,真相是什么呢?;-)
你能用Java 8编译一个类,然后在Java 7中使用它吗?
我想写一个具有简单接口(与Java 7兼容)的实用程序JAR,但在内部到处使用lambdas。然后我想在一些必须用JDK 7编译的代码中使用该实用程序。
可能吗?
如您所见,有一些相互矛盾的答案。那么,真相是什么呢?;-)
在使用 java 8 进行编译时,您可以使用 javac 来制作在 java 7 上运行的 .类。但是,您不会获得java 8功能,例如lambdas,因为您还必须使用1.7作为源值。-source 1.7 -target 1.7
不过,这并不是故事的结局。在这个答案中,有人解释说实际上没有新的JVM指令,所以这应该是可能的。在这个答案中,引入了 retrolambda 工具,它可用于在较旧的 JVM 上运行 java 8 代码。作者声称不需要编译步骤,只需一个 java 代理转换类。他的解决方案仅处理 lambdas,而不处理任何其他功能。当然,这不会给你带来java 8附带的新API或其他改进,但至少它会让你的要求成为可能。一些新的api也被非正式地向后移植,即java.util.stream和java.time。
如果我们处于java8之前的时代,即使javac不支持,你仍然可以使用编译器API来做同样的事情。此外,Eclipse编译器已经能够做到这一点,以及使用上述两个选项之一的ant和maven任务(编译器插件默认使用javac)。这似乎不再那么简单,因为使用其他编译器,你也需要lambda等功能的实现,编译器API将抛出与其他人相同的“javac:源版本1.8需要目标版本1.8”。-source 1.8 -target 1.7
对于感兴趣的人,以下是使用Eclipse编译器和Maven以及计算器示例代码发生的情况:
pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>fi.eis.applications.java8</groupId>
<artifactId>calculator</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.7</target>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
在 Windows 上执行:
>mvn clean compile
[..snip..]
[INFO] BUILD SUCCESS
>cd target\classes
>"%JAVA_HOME%\bin\java.exe" Calculator
Exception in thread "main" java.lang.NoClassDefFoundError: java/lang/invoke/LambdaMetafactory
at Calculator.main(Calculator.java:16)
Caused by: java.lang.ClassNotFoundException: java.lang.invoke.LambdaMetafactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
因此,需要将这些类作为第三方库在纯java中实现,才能使其正常工作。
这是不可能的,如果你在较新的Java版本中编译东西,它们将无法执行。