安卓和Lambda

12

我需要将一些使用Java lambda函数的代码集成。我的几个限制要求我使用Eclipse Mars,最新的ADT插件而不是Android Studio来开发项目。

问题在于使用Lambda函数需要使用1.8 JDK兼容性,但如果设置成这样,我会收到以下消息:

Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead.

如何让这两者和谐共存?

编辑:这不是一个重复的问题,因为我在询问关于ADT Eclipse的问题,而自那个问题以来,Android已经支持Java 8,所以这不仅不是一个重复的问题,而且那个问题现在已经过时(距离上次更新已经1.5年)。


1
可能是Which JDK version (Language Level) is required for Android Studio?的重复问题。 - Michael Easter
阅读错误信息是无法解决问题的。你只能等待Android支持Java 8。 - Andy Turner
我知道我可以在AS中使用Lambda函数,那么为什么不能在ADT中使用呢? - Ysch
4
Android上的Java运行环境(即Dalvik或ART)与J2EE和J2SE运行时是完全独立的。一个平台的功能不一定存在于另一个平台上。 - dhke
停止使用Eclipse,改用Android Studio。 - Jared Burrows
显示剩余6条评论
6个回答

11

Java 8 语言特性在 Android 上的更新

Lambda 表达式已经被移植到旧版本的 Android。

这是 Android Gradle Plugin 3.0 及以上版本的一个功能,将 lambda 表达式与其他 Java 8 语言特性一起移植到旧版 Android 操作系统中。

请将以下内容添加到您的 Gradle 构建脚本中,以启用该功能。

android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

获取更多详情,请参阅使用 Java 8 语言功能Android 的 Java 8 支持

如 @dhke 所说,Android 目前还没有支持 Java 8。

使用 Java 8,构建 Java 6/7

但是,您仍然可以使用 JDK 8 来开发 Android 应用。只需根据您的minSDKVersion将源兼容性设置为 6 或 7。因此,您会失去 Java 8 中引入的任何新功能,例如在您的情况下的 lambda。

Lambda 的后移

由于您广泛使用 lambda,Retrolambda 可能是您的选择。它为预 Java 8 版本提供了 Lambda 的后移。它有 Maven/Gradle/命令行插件来启用支持。

其他后移

如果您需要其他 Java 8 功能,据我所知,ThreeTen ABP 为 Java 8 日期时间 API 提供了后移支持。


1
其他后移的补充说明 - streamsupport项目提供了Java 8 Stream API的后移版本:https://sourceforge.net/projects/streamsupport - Stefan Zobel
Android Studio现在支持Java 8! - Mahdi Moqadasi

6

目前(至少在Android 5.1.1之前),您无法在Android上使用lambda函数。

Lambda函数需要新的Dalvik(不一定是JVM!)操作码(liberate-variable、box-lambda、unbox-lambda、capture-variable、create-lambda、invoke-lambda),目前Dalvik和ART都没有支持。

看起来Google可能已经计划(尽管似乎还没有正式宣布)在5.1.1之后(API级别23及更高版本)支持Java 8。至少,smali反汇编器已经添加了对该API级别的明确引用:

https://github.com/JesusFreke/smali/commit/144951a9e9e6c87866245f2bdeebf0ebedaa0e38:

添加新的-X / --experimental标志以 [dis]assemble尚未在art中的操作码

  • 添加新的操作码liberate-variable、box-lambda、unbox-lambda、capture-variable、create-lambda、invoke-lambda
  • 添加对25x指令的编码支持
  • 添加LambdaTest以检查新操作码的组装/反汇编是否正确

还有

https://github.com/JesusFreke/smali/commit/144951a9e9e6c87866245f2bdeebf0ebedaa0e38#diff-5d7892344c0b747d3667bf8623c690c5R66

options.apiLevel = 23;  // since we need at least level 23 for lambda opcodes

这只是标记操作码,而不是必要的库更改。它也没有告诉我们有关Android本身的任何信息,因此我建议不要将其视为官方发布计划。


1
Java 8对于lambda表达式的实现并没有引入任何新的“操作码”。相反,它建立在invokedynamic指令之上,这是Java 7的一个特性(是的-在Android上不存在)。事实上,如果所需的API类存在于Java 7 VM中,Java 8 lambda字节码可以在其中运行。 - Stefan Zobel

3
Android支持Java 8,因此这不是重复内容。从Android N预览版开始,Android支持有限的Java 8功能,请参见Java 8语言特性
要开始使用这些功能,您需要下载和设置Android Studio 2.1和Android N预览版SDK,其中包括所需的Jack工具链和更新的Android Gradle插件。如果您尚未安装Android N预览版SDK,请参阅设置用于开发Android N支持的Java 8语言特性和API

目前Android不支持所有Java 8语言特性。 然而,在开发针对Android N预览版的应用程序时,以下功能现在可用:

默认和静态接口方法

Lambda表达式

可重复注释

还有一些其他的Java 8功能是Android支持的,您可以从Java 8语言特性中查看完整的详细信息。


谢谢你的回答,但我已经知道如何在AS中启用Lambda表达式了,我的问题是如何在ADT Eclipse中启用它。 - Ysch

1

我认为这不会起作用。

为了使用lambda表达式,您需要源兼容性级别1.8。为了使DEX编译器工作,您需要目标兼容性1.7。Eclipse不会让您将目标兼容性设置低于源兼容性(如下图所示)。

请注意,这与IntelliJ认为它比您更了解代码应该是什么的习惯无关。即使实际代码是匿名类,它也可以显示lambda表达式。

enter image description here


1
自几天前起,Android Studio 3.0 正式版已经发布。它正式支持 Java 8 特性的一个子集,其中包括 lambda 表达式
根据这篇 Android 开发者博客文章(2017 年 3 月 14 日),Google 决定将对 Java 8 语言特性提供直接支持,以取代 Jack 工具链,并将其纳入 javac 和 dx 工具集中。通过此新方向,现有的依赖于 Java 类文件格式的工具和插件应该继续有效。未来,Android 构建系统将原生支持 Java 8 语言特性。我们计划在未来几周内作为 Android Studio 的一部分推出这项功能,并希望尽早与您分享这个决定。
因此,我们可能不必再等待太久才能在 Android Studio 中使用 Java 8。

0

反转Lambda语法

据我所知,使用新的Java 8 Lambda语法完成的所有操作都可以使用老式的Java代码(如匿名内部类)来完成。(Oracel教程) (Oracle快速入门)

为了简化撤销Lambda语法的负担,一些IDE(如NetBeans)可以建议自动修订代码,以便在Lambda语法之间进行单向/双向转换。只需点击一下批准按钮,语法就会自动交换。请参阅NetBeans文档中的使用Lambda表达式支持

这是NetBeans的屏幕截图,它提供将Vaadin按钮的Button.ClickListener从Lambda语法转换为匿名内部类。请注意鼠标指针单击第107行上的灯泡图标。

screenshot of NetBeans offering to switch Lambda syntax to an anonymous inner class

要在您的IDE中启用此功能,您需要暂时在项目中启用Java 8。撤消所有Lambda语法后,将项目切换回Java 6/7。在NetBeans中启用Java 8的方法是在项目 > 属性 > 源 > 源/二进制格式(弹出菜单)> 1.8


我不知道有自动切换lambda和匿名方法的工具。听起来很有前途,我会研究一下! - Ysch
我不知道有关项目范围编辑的情况,但可能存在。当然,NetBeans 8.0.2确实建议在类代码编辑器中切换到/从Lambda语法。我每天都使用这个功能。 - Basil Bourque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接