• 使用 Java 8 语言功能
    • 支持的 Java 8 语言功能和 API
    • 迁移至默认工具链
      • 从 Jack 迁移
      • 从 Retrolambda 迁移
    • 停用对 Java 8 语言功能的支持

    使用 Java 8 语言功能

    Android Studio 3.0 及以上版本支持所有 Java 7 语言功能,以及部分 Java 8 语言功能(具体因平台版本而异)。 本页介绍您可以使用的 Java 8 语言功能、如何正确配置项目以使用这些功能以及您可能遇到的任何已知问题。

    注:在开发 Android 应用时,可以选择使用 Java 8 语言功能。 您可以将项目的源代码和目标代码兼容性值保留为 Java 7,但仍须使用 JDK 8 进行编译。

    Android Studio 为使用部分 Java 8 语言功能及利用这些功能的第三方库提供内置支持。 如图 1 所示,默认工具链对 javac 编译器的输出执行字节码转换(称为 desugar),从而实现新语言功能。 Jack 不再受支持,您需要首先停用 Jack 才能使用默认工具链内置的 Java 8 支持。

    使用 Java 8 语言功能 - Use Java 8 language features - 图1

    图 1. 采用 desugar 字节码转换的 Java 8 语言功能支持。

    要开始使用受支持的 Java 8 语言功能,请更新 Android 插件到 3.0.0(或更高版本)。 然后,针对使用(包括在源代码中或通过依赖项使用)Java 8 语言功能的每个模块,在其 build.gradle 文件中添加以下代码:

    1. android {
    2. ...
    3. // Configure only for each module that uses Java 8
    4. // language features (either in its source code or
    5. // through dependencies).
    6. compileOptions {
    7. sourceCompatibility JavaVersion.VERSION_1_8
    8. targetCompatibility JavaVersion.VERSION_1_8
    9. }
    10. }

    注:如果 Android Studio 检测到您的项目使用的是 Jack、Retrolambda 或 DexGuard,IDE 则会使用由这些工具提供的 Java 8 支持。 但您可以考虑迁移至默认工具链。

    支持的 Java 8 语言功能和 API

    虽然 Android Studio 并非支持所有 Java 8 语言功能,但未来发布的 IDE 版本将会增加更多功能。 目前,部分功能和 API 已可使用,具体取决于您所使用的 minSdkVersion,详见下表。

    Java 8 语言功能兼容的 minSdkVersion
    Lambda 表达式任意。 然而,只有在 Lambda 采集的所有值可序列化时才支持 Lambda 序列化。
    函数引用任意。
    类型注解任意。 然而,类型注解信息仅在编译时可用,在运行时不可用。 此外,在 API 级别 24 及更低级别中,平台支持 TYPE,而不支持 ElementType.TYPE_USEElementType.TYPE_PARAMETER
    默认和静态接口函数任意。
    重复注解任意。
    Java 8 Language API兼容的 minSdkVersion
    java.lang.annotation.RepeatableAPI 级别 24 或更高级别。
    AnnotatedElement.getAnnotationsByType(Class)API 级别 24 或更高级别。
    java.util.streamAPI 级别 24 或更高级别。
    java.lang.FunctionalInterfaceAPI 级别 24 或更高级别。
    java.lang.reflect.Method.isDefault()API 级别 24 或更高级别。
    java.util.functionAPI 级别 24 或更高级别。

    除了上述 Java 8 语言功能和 API 之外,Android Studio 3.0 及更高版本还将对 try-with-resources 的支持扩展到所有级别的 Android API。

    Desugar 目前暂不支持 MethodHandle.invokeMethodHandle.invokeExact。如果您的源代码或任一模块依赖项使用了其中一种函数,则需指定 minSdkVersion 26 或更高版本。 否则会出现以下错误:

    1. Dex: Error converting bytecode to dex:
    2. Cause: signature-polymorphic method called without --min-sdk-version >= 26

    在某些情况下,即使您的模块包含在库依赖项中,也可能不会使用 invokeinvokeExact 函数。 因此,要继续使用 minSdkVersion 25 或更低版本的库,请通过启用代码压缩 移除未使用的函数。 如果这种方法无效,可考虑使用一个替代库,该库不使用未受支持的函数。

    迁移至默认工具链

    如果 Android Studio 检测到您的项目使用了 Jack、Retrolambda 或 DexGuard,IDE 则会使用由这些工具提供的 Java 8 支持。 但与默认工具链相比,这些工具缺乏部分功能和支持。 所以,请参照本节说明迁移至 Android Studio 的默认工具链。

    从 Jack 迁移

    根据此公告,Jack 工具链已经被弃用。如果您的项目依赖 Jack,则应执行迁移,以便享受到 Android Studio 默认工具链所内置的 Java 8 支持。 使用默认工具链还支持使用 Java 8 语言功能的第三方库、Instant Run 以及依靠 .class 中间文件的工具。

    要停用 Jack 并切换至默认工具链,只需从您的模块 build.gradle 文件中移除 jackOptions 块即可:

    1. android {
    2. ...
    3. defaultConfig {
    4. ...
    5. // Remove this block.
    6. jackOptions {
    7. enabled true
    8. ...
    9. }
    10. }
    11. // Keep the following configuration in order to target Java 8.
    12. compileOptions {
    13. sourceCompatibility JavaVersion.VERSION_1_8
    14. targetCompatibility JavaVersion.VERSION_1_8
    15. }
    16. }

    从 Retrolambda 迁移

    与 Android Studio 的默认工具链相比,Retrolambda 缺少对使用 Java 8 语言功能的第三方库的支持。 要迁移到默认工具链,请从您的项目级 build.gradle 文件中移除 Retrolambda 依赖项:

    1. buildscript {
    2. ...
    3. dependencies {
    4. // Remove the following dependency.
    5. classpath 'me.tatarka:gradle-retrolambda:<version_number>'
    6. }
    7. }

    同时移除每个模块 build.gradle 文件中的 Retrolambda 插件和 retrolambda 块:

    1. // Remove the following plugin.
    2. apply plugin: 'me.tatarka.retrolambda'
    3. ...
    4. // Remove this block after migrating useful configurations.
    5. retrolambda {
    6. ...
    7. // If you have arguments for the Java VM you want to keep,
    8. // move them to your project's gradle.properties file.
    9. jvmArgs '-Xmx2048m'
    10. }

    停用对 Java 8 语言功能的支持

    如果您遇到与 Java 8 语言功能支持相关的问题,可在 gradle.properties 文件中加入以下代码来停用此支持:

    1. android.enableDesugar=false

    为帮助我们改进对 Java 8 的支持,请提交错误。