Save the date! Android Dev Summit is coming to Mountain View, CA on November 7-8, 2018.

使用 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 语言功能的每个模块,在其 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
  }
}

注:如果 Android Studio 检测到您的项目使用的是 Jack、RetrolambdaDexGuard,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.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
    }
}

从 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 的支持,请提交错误