サーチ…


前書き

Androidは、すべてのJava 7言語機能とプラットフォームバージョンによって異なるJava 8言語機能のサブセットをサポートしています。このページでは、使用できる新しい言語機能、それらを使用するためのプロジェクトの適切な設定方法、および遭遇する可能性のある既知の問題について説明します。

Retrolambdaを使ってJava 8の機能をサブセット化

Retrolambdaを使用すると、ラムダ式、メソッド参照、およびJava 7,6または5でのtry-with-resourcesステートメントでJava 8コードを実行できます。これは、Java 8コンパイル済みバイトコードを変換して古いJavaランタイムで実行できるようにすることで行います。

バックポート言語の機能:

  • ラムダ式は匿名の内部クラスに変換することによってバックポートされます。これには、ステートレスラムダ式にシングルトンインスタンスを使用して繰り返しオブジェクトを割り当てるのを最適化することが含まれます。メソッド参照は基本的にラムダ式の構文砂糖であり、同じ方法でバックポートされます。

  • ターゲットのバイトコードのバージョンがJava 7未満の場合、 Throwable.addSuppressedへの呼び出しを削除することで、Try-with-resourcesステートメントがバックポートされます。抑止された例外が取り込まれるのではなくログに記録されるようにするには、構成可能です。

  • Objects.requireNonNullコールはへの呼び出しに置き換えられObject.getClassターゲットバイトコードのバージョンは、Java 7 JDK 9の使用によって生成された合成ヌルチェック下回る場合Objects.requireNonNull以前のJDKバージョンが使用されるのに対し、 Object.getClass

  • オプション:

    1. デフォルトメソッドは、静的メソッドとしてコンパニオンクラス(インターフェイス名+ "$")にデフォルトメソッドをコピーし、インターフェイスのデフォルトメソッドを抽象メソッドに置き換え、必要なメソッド実装をそのインターフェイスを実装するすべてのクラスに追加することによってバックポートされます。

    2. 静的メソッドをコンパニオンクラス(インターフェイス名+ "$")に移動し、すべてのメソッド呼び出しを変更して新しいメソッドの場所を呼び出すことで、インターフェイスの静的メソッドがバックポートされます。

既知の制限:

  • Java 8 APIをバックポートしない

  • インターフェース上のバックポートのデフォルトメソッドと静的メソッドには、すべてのバックポートされたインターフェースと、それを実装するすべてのクラス、またはスタティックメソッドを一緒にバックポートするよう呼び出され、Retrolambdaを1回実行する必要があります。つまり、常にきれいなビルドを行う必要があります。また、バックポートのデフォルトメソッドは、モジュールまたは依存関係の境界を越えて機能しません。

  • 将来のJDK 8ビルドがinvokedynamic呼び出しごとに新しいクラスの生成を停止した場合に壊れる可能invokedynamicます。 Retrolambdaは、 java.lang.invoke.LambdaMetafactoryが動的に生成するバイトコードをキャプチャするように動作しjava.lang.invoke.LambdaMetafactory 。そのため、そのメカニズムに対する最適化はRetrolambdaを破損する可能性があります。

Retrolambda gradleプラグインは自動的にRetrolambdaであなたのアンドロイドプロジェクトを構築します。最新版は、 リリースページにあります

使用法:

  1. jdk8をダウンロードしてインストールする
  2. build.gradle以下を追加してください
buildscript {
  repositories {
     mavenCentral()
  }

  dependencies {
     classpath 'me.tatarka:gradle-retrolambda:<latest version>'
  }
}

// Required because retrolambda is on maven central
repositories {
  mavenCentral()
}

apply plugin: 'com.android.application' //or apply plugin: 'java'
apply plugin: 'me.tatarka.retrolambda'

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

既知の問題点:

  • Lambdaを持つJavaファイルでLintが失敗します。 AndroidのリントはJava 8の構文を理解していないため、静かにまたは大声で失敗します。問題を解決する実験的なフォークがあります。

  • Google Playサービスを使用するとRetrolambdaが失敗します。バージョン5.0.77には、Retrolambdaと互換性のないバイトコードが含まれています。これは、新しいバージョンのプレイサービスで修正する必要があります。アップデートできる場合は、これが推奨されるソリューションになります。この問題を-noverifyするには、4.4.52などの以前のバージョンを使用するか、jvm argsに-noverifyを追加します。

retrolambda {
  jvmArgs '-noverify'
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow