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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21014338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:56:37  来源:igfitidea点击:

Can you compile a class using Java 8 and then use it in Java 7?

javajava-8

提问by Kalamar Obliwy

Can you compile a class using Java 8 and then use it in Java 7?

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

I'd like to write a utility JAR with a simple interface (Java 7 compatible) but using lambdas all over the place inside. Then I'd like to use the utility in some code that has to be compiled with JDK 7..

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

is it possible?

是否可以?



As you can see, there are some contradictory answers.. so, what's the truth? ;-)

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

回答by user3149442

It is not possible, if you compile things in newer Java version they'll be un executable.

这是不可能的,如果您在较新的 Java 版本中编译内容,它们将无法执行。

回答by eis

You can use -source 1.7 -target 1.7when compiling with java 8 javac to make .classes that work on java 7. However, you don't get java 8 features such as lambdas then, as you have to use 1.7 as source value as well.

您可以-source 1.7 -target 1.7在使用 java 8 javac 编译时使用来制作在 java 7 上运行的 .classes。但是,您不会获得 java 8 功能,例如 lambdas,因为您还必须使用 1.7 作为源值。

That's not the end of story though. In this answerit was explained that there aren't actually new JVM instructions, so this should be possible. In this answerthe tool retrolambdawas introduced which can be used to run java 8 code on older JVMs. Author claims that compilation step is not required, just a java agent transforming the classes. His solution deals with lambdas only, not any other features. Of course, that won't bring you the new APIs coming with java 8, or other improvements, but at least it would make what you ask possible. Some of the new apis have also been unofficially backported, namely java.util.streamand java.time.

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



If we were in pre-java8 era, even though -source 1.8 -target 1.7is not supported by javacyou could still use Compiler APIto do the same. Also Eclipse compiler has been able to do this, as well as ant and maven tasks that use either of the two mentioned options (compiler-plugin uses javac by default). This doesn't seem to no longer be so straight forward, as using other compilers you'd need the implementations of features like lambdas as well, and Compiler API will throw the same "javac: source release 1.8 requires target release 1.8" as others.

如果我们在 java8 之前的时代,即使-source 1.8 -target 1.7javac 不支持,您仍然可以使用Compiler API来做同样的事情。Eclipse 编译器也能够做到这一点,以及使用上述两个选项之一的 ant 和 maven 任务(编译器插件默认使用 javac)。这似乎不再那么直截了当,因为使用其他编译器,您还需要实现 lambdas 等功能,并且编译器 API 将抛出与其他相同的“javac:源版本 1.8 需要目标版本 1.8” .

For the interested, here's what happens going that way using Eclipse compiler & Maven and Calculator example code:

对于感兴趣的人,这里是使用 Eclipse 编译器 & Maven 和计算器示例代码发生的事情:

pom.xml:

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>

Execution on Windows:

在 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.run(URLClassLoader.java:366)
        at java.net.URLClassLoader.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

So one would need to implement those classes in pure java as a third party library to get that to work.

因此,需要在纯 Java 中将这些类实现为第三方库才能使其正常工作。

回答by Rugal

You ca easily achieve this in maven pom.xmlwith plugin:

您可以pom.xml使用插件在 Maven 中轻松实现这一点:

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

just as indicated that you can compile under 1.8and to 1.6which might have best compatibility with JavaSE 6

正如所指出的,您可以在可能与 JavaSE 6 具有最佳兼容性的情况下1.8进行编译1.6