【问题标题】:Can you compile a class using Java 8 and then use it in Java 7? [duplicate]您可以使用 Java 8 编译一个类,然后在 Java 7 中使用它吗? [复制]
【发布时间】:2014-01-09 07:42:47
【问题描述】:

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

我想编写一个具有简单接口(Java 7 兼容)的实用 JAR,但在里面到处都使用 lambda。然后我想在一些必须用 JDK 7 编译的代码中使用该实用程序..

有可能吗?


如您所见,有一些相互矛盾的答案。那么,真相是什么? ;-)

【问题讨论】:

标签: java java-8


【解决方案1】:

您可以在使用 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 代理。他的解决方案只处理 lambda,而不处理任何其他特性。 当然,这不会为您带来 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 中实现这些类作为第三方库才能使其正常工作。

【讨论】:

  • @KalamarObliwy 你认为这里有什么遗漏或错误吗,因为答案未被接受?
【解决方案2】:

这是不可能的,如果你用较新的 Java 版本编译它们,它们将是不可执行的。

【讨论】:

  • 不正确,您可以在使用 java 8 编译时使用-target 来制作适用于 java 7 的 .classes。但是,您将无法获得 java 8 的功能,例如 lambdas。
【解决方案3】:

你可以通过插件在 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 具有最佳兼容性

【讨论】:

  • 如果我使用非 1.7 功能,这将编译 1.8 代码 - 确切地说是 lambdas?
  • @KalamarObliwy 因为 1.7 没有 lambda 表达式,所以你不能使用它!
  • @Rugal 但这正是 OP 所要求的。这与 javac 的 -source-target 选项相同,编译器插件不会在那里增加任何功能优势。
  • @KalamarObliwy 同意,我知道javac 有这个选项。我提供的是实现这一目标的便捷方式!
  • @Rugal 我在一个使用 Maven 3.1.1 的简​​单项目中尝试了你的 pom sn-p,但编译失败与 Java 文件内容无关。你确定这对你有用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-15
  • 1970-01-01
  • 2017-04-13
  • 2014-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多