使用 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 支持。

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

要开始使用受支持的 Java 8 语言功能,请将 Android 插件更新3.0.0(或更高版本)。在此之后,针对使用(在源代码中使用或通过依赖项使用)Java 8 语言功能的每个模块,在 Project Structure 对话框(依次点击 File > Project Structure)中将 Source CompatibilityTarget Compatibility 更新为 1.8,如图 2 所示。

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

您也可以直接在相应的 build.gradle 文件中进行配置:

android {
      ...
      // Configure only for each module that uses Java 8
      // language features (either in its source code or
      // through dependencies).
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
      // For Kotlin projects
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    

注意:如果 Android Studio 检测到您的项目正在使用 Jack、RetrolambdaDexGuard,IDE 会使用由这些工具提供的 Java 8 支持。不过,可考虑迁移到默认工具链

支持的 Java 8 语言功能和 API

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

Java 8 语言功能 兼容的 minSdkVersion
Lambda 表达式 全部。请注意,Android 不支持 lambda 表达式的序列化。
方法引用 全部。
类型注解 全部。不过,类型注解信息在编译时可用,但在运行时不可用。此外,在 API 级别 24 及更低级别中,平台支持 TYPE,但不支持 ElementType.TYPE_USEElementType.TYPE_PARAMETER
默认和静态接口方法 全部。
重复注解 全部。
Java 8 语言 API 兼容的 minSdkVersion
java.lang.annotation.Repeatable API 级别 24 或更高级别。
AnnotatedElement.getAnnotationsByType(Class) API 级别 24 或更高级别。
java.util.stream API 级别 24 或更高级别。
java.lang.FunctionalInterface API 级别 24 或更高级别。
java.lang.reflect.Method.isDefault() API 级别 24 或更高级别。
java.util.function API 级别 24 或更高级别。

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

Desugar 目前暂不支持 MethodHandle.invokeMethodHandle.invokeExact。如果您的源代码或某个模块依赖项使用其中一种方法,则需要指定 minSdkVersion 26 或更高版本。否则,您会遇到以下错误:

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

在某些情况下,即使 invokeinvokeExact 方法包含在库依赖项中,您的模块也可能不使用这些方法。因此,要在指定了 minSdkVersion 25 或更低版本的情况下继续使用该库,请启用代码压缩来移除未使用的方法。如果这样做不起作用,可考虑使用一个替代库,让其不使用不受支持的方法。

迁移到默认工具链

如果 Android Studio 检测到您的项目正在使用 Jack、RetrolambdaDexGuard,IDE 会使用由这些工具提供的 Java 8 支持。不过,与默认工具链相比,这些工具缺少部分功能和支持。因此,请按照本部分的说明迁移到 Android Studio 的默认工具链。

从 Jack 迁移

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

要停用 Jack 而改用默认工具链,只需从模块的 build.gradle 文件中移除 jackOptions 代码块即可:

android {
        ...
        defaultConfig {
            ...
            // Remove this block.
            jackOptions {
                enabled true
                ...
            }
        }

        // Keep the following configuration in order to target Java 8.
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
        // For Kotlin projects
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    

从 Retrolambda 迁移

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

buildscript {
      ...
       dependencies {
          // Remove the following dependency.
          classpath 'me.tatarka:gradle-retrolambda:<version_number>'
       }
    }
    

此外,还应从每个模块的 build.gradle 文件中移除 Retrolambda 插件和 retrolambda 代码块:

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

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

如果您遇到与 Java 8 语言功能支持相关的问题,您可以通过将以下代码添加到 gradle.properties 文件来停用该支持:

android.enableDesugar=false
    

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