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 言語機能の使用を開始するには、3.0.0(またはそれ以上)のバージョンに Android プラグインを更新します。その後、Java 8 言語機能を(ソースコード内で、または依存関係を通じて)使用する各モジュールについて、[Project Structure] ダイアログ([File] > [Project Structure] をクリック)で [Source Compatibility] と [Target 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"
      }
    }
    

注: プロジェクトが Jack、Retrolambda、または DexGuard を使用していることが Android Studio により検出されると、IDE ではこれらのツールが提供する Java 8 サポートが使用されますが、デフォルトのツールチェーンへの移行を検討してください。

サポートされる Java 8 言語機能と API

Android Studio はすべての Java 8 言語機能をサポートしているわけではありませんが、IDE の将来のリリースではさらに多くの機能が追加される予定です。使用している minSdkVersion に応じて、次の表に示す特定の機能と API を使用できます。

Java 8 言語機能 互換性のある minSdkVersion
ラムダ式 すべて。ただし、Android はラムダ式のシリアル化をサポートしていません。
メソッド参照 すべて。
型アノテーション すべて。ただし、型アノテーション情報は、実行時ではなくコンパイル時に使用できます。また、プラットフォームは API レベル 24 以下の TYPE をサポートしますが、ElementType.TYPE_USE または ElementType.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 以上。

Android Studio 3.0 以降では、上記の Java 8 言語機能と API に加えて、すべての Android API レベルに try -with-resources のサポートが拡張されています。

Desugar は現在 MethodHandle.invoke または MethodHandle.invokeExact をサポートしていません。ソースコードまたはいずれか 1 つのモジュールの依存関係でこれらのメソッドのいずれかが使用されている場合は、minSdkVersion 26 以上を指定する必要があります。そうしないと、次のエラーが返されます。

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

場合によっては、モジュールがライブラリの依存関係に含まれていても、モジュールが invoke メソッドまたは invokeExact メソッドを使用しないことがあります。したがって、minSdkVersion 25 以下でこのライブラリを使用し続けるには、コードの圧縮を有効化して未使用のメソッドを削除します。この方法がうまくいかない場合は、サポートされていないメソッドを使用しない代替ライブラリの使用を検討してください。

デフォルトのツールチェーンへの移行

プロジェクトが Jack、Retrolambda、または DexGuard を使用していることが Android Studio により検出されると、IDE ではこれらのツールが提供する Java 8 サポートが使用されます。ただし、デフォルトのツールチェーンとは異なり、これらのツールには一部の機能とサポートが含まれていません。したがって、このセクションの手順に従って、Android Studio のデフォルトのツールチェーンに移行してください。

Jack からの移行

こちらのお知らせにあるとおり、Jack ツールチェーンは非推奨になりました。プロジェクトが Jack に依存している場合は、Android Studio のデフォルトのツールチェーンに組み込まれている Java 8 サポートを使用するよう切り替える必要があります。デフォルトのツールチェーンを使用すると、Java 8 言語機能、中間 .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 からの移行

Retrolambda は、Android Studio のデフォルトのツールチェーンとは異なり、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 ファイルに次の行を追加して、Java 8 言語機能のサポートを無効にできます。

android.enableDesugar=false
    

Java 8 のサポートの改善のために、バグの報告をお願いします。