2014-01-09 2 views
21

Можете ли вы скомпилировать класс с использованием Java 8, а затем использовать его в Java 7?Можете ли вы скомпилировать класс с использованием Java 8, а затем использовать его в Java 7?

Я хотел бы написать утилиту JAR с простым интерфейсом (совместимость с Java 7), но с использованием лямбда повсюду внутри. Затем я хотел бы использовать утилиту в некотором коде, который должен быть скомпилирован с помощью JDK 7.

Возможно ли это?

Как вы можете видеть, есть некоторые противоречивые ответы .. так, что это правда? ;-)

+0

Установите этот флажок, ответ на тот же вопрос с java 7 и 6: http: // stackoverflow.ком/вопросы/17347589/проверить, Java-версия совместимость/17347680 # 17347680 [1]: http://stackoverflow.com/questions/17347589/verify-java-version-compatibility/17347680#17347680 – MoYapro

+0

Да, я думал об этом, потому что AFAIK не содержит новых инструкций по байт-коду, поэтому, возможно, если вы скомпилируете его, у него будет возможность запускать. –

ответ

-4

Это невозможно, если вы скомпилируете вещи в новой версии Java, они не будут исполняться.

+5

Неверно, вы можете использовать '-target' при компиляции с java 8. Чтобы сделать .classes которые работают на java 7. Однако вы не получите java 8 функций, таких как lambdas. – eis

31

Вы можете использовать -source 1.7 -target 1.7 при компиляции с java 8 javac, чтобы сделать .classes, которые работают на java 7. Однако вы не получаете java 8 функций, таких как lambdas, так как вам нужно использовать значение 1.7 в качестве исходного значения ,

Это еще не конец истории. В this answer было объяснено, что на самом деле нет новых инструкций JVM, поэтому это должно быть возможно. В this answer был введен инструмент retrolambda, который может использоваться для запуска кода java 8 на старых JVM. Автор утверждает, что этап компиляции не требуется, просто агент Java, преобразующий классы. Его решение касается только лямбда, а не каких-либо других функций. Конечно, это не принесет вам новых API-интерфейсов с java 8 или другими улучшениями, но, по крайней мере, это сделает то, что вы попросите. Некоторые из новых apis также были неофициально предоставлены, а именно java.util.stream и java.time.


Если бы мы были в предварительном java8 эпоху, несмотря на то, -source 1.8 -target 1.7is not supported by javac вы могли использовать Compiler API сделать то же самое. Также компилятор Eclipse смог это сделать, а также задачи ant и maven, которые используют один из двух указанных опций (по умолчанию используется компилятор-плагин javac). Это, похоже, уже не так прямолинейно, как использование других компиляторов, для которых вам понадобятся реализации таких функций, как lambdas, а API компилятора будет использовать тот же «javac: source release 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

@KalamarВозможно, вы думаете, что здесь что-то не так или нет, так как ответ был неприемлем? – eis

-4

Вы ча легко добиться этого в мавена 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.8 и 1.6, которые могли бы иметь лучшую совместимость с JavaSE 6

+0

Это скомпилирует код 1.8, если я использую функции не-1.7 - lambdas, если быть точным? –

+0

@KalamarObliwy Поскольку у 1.7 нет выражения лямбды, вы не могли бы это использовать! – Rugal

+2

@Rugal, но это была вещь, о которой просил. Это то же самое, что опции '-source' и' -target' javac, плагин компилятора не добавляет никакого функционального преимущества. – eis

Смежные вопросы