你能用Java 8编译一个类,然后在Java 7中使用它吗?

时间:2014-01-09 07:42:48

标签: java java-8

您可以使用Java 8编译一个类,然后在Java 7中使用它吗?

我想编写一个带有简单接口(Java 7兼容)的实用程序JAR,但在整个地方使用lambdas。然后我想在一些必须用JDK 7编译的代码中使用该实用程序。

有可能吗?


正如你所看到的,有一些相互矛盾的答案......那么,真相是什么? ; - )

3 个答案:

答案 0 :(得分:31)

使用java 8 javac编译时可以使用-source 1.7 -target 1.7来生成适用于java 7的.classes。但是,你不能使用lambdas之类的java 8功能,因为你必须使用1.7作为源代码价值也是如此。

但这不是故事的结局。在this answer中,有人解释说实际上没有新的JVM指令,所以这应该是可行的。在this answer中引入了工具retrolambda,该工具可用于在较旧的JVM上运行java 8代码。作者声称编译步骤不是必需的,只是一个转换类的java代理。他的解决方案只涉及lambdas,而不涉及任何其他功能。 当然,这不会为您带来Java 8附带的新API或其他改进,但至少它会使您提出的要求成为可能。一些新的api也被非正式地向后移植,即java.util.streamjava.time


如果我们处于java8之前的时代,即使-source 1.8 -target 1.7 is not supported by javac你仍然可以使用Compiler API来做同样的事情。此外,Eclipse编译器已经能够执行此操作,以及使用上述两个选项之一的ant和maven任务(编译器插件默认使用javac)。这似乎不再那么直接,因为使用其他编译器你也需要像lambdas这样的功能的实现,而编译器API将抛出相同的“javac:源版本1.8需要目标版本1.8”作为其他

对于感兴趣的人来说,这是使用Eclipse编译器& Maven和Calculator example code

的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中将这些类实现为第三方库,以使其工作。

答案 1 :(得分:-4)

如果你在较新的Java版本中编译它们是不可能的,那是不可能的。

答案 2 :(得分:-4)

您可以使用插件轻松地在maven pom.xml中实现此目的:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <source>1.8</source>
        <target>1.7</target>
        <compilerArgument></compilerArgument>
    </configuration>
 </plugin>

正如所示,您可以在1.81.6之下进行编译,这可能与JavaSE 6具有最佳兼容性