「Android NでJava8がサポートされた」とはどういうことか

追記: StreamやOptionalはpreview-2で実装されたようです。

gfx.hatenablog.com


Android N previewが公開されましたね!このバージョンではJava8のサポートがあると発表されています。また、標準クラスライブラリがOpenJDKベースの実装になったことで、Java8との互換性が高まるのではないかという前評判もありました。

First Preview of Android N: Developer APIs & Tools | Android Developers Blog

本エントリでは、この「Android NでJava8」について解説します。

三行まとめ

  • Android N runtimeはOpenJDK7ベースで、Java8クラスライブラリは一部のみ移植されている
  • Android N SDKに同梱されているJackコンパイラはlambdaなどの一部のJava8の構文を古いAndroid向けのdexにコンパイルできる
  • JackコンパイラができることはRetrolambdaとほぼおなじで、Android Nと直接は関係ない

解説

さて、「Android Nで」というのは、まず2つの意味があります。

  • Android Nの世代のAndroid SDKで開発するとき
    • compileSdkVersion=N かつ targetSdkVersion=N を要求することもあるものの、基本的には動作するAndroidのバージョンにはそれほど依存しない
  • Androidアプリケーションを動かすOSがAndroid N以上のとき
    • つまりNランタイムのうえで動作するとき

この2つを混同してはいけません。この記事では前者を「N SDK」、後者を「N runtime」と呼ぶことにします。

またさらに、公式サイトによれば、一部のJava8の機能は新しいJava Android Compiler Kit "Jack" でのみ提供されるとあります。これは、フルスクラッチで開発された*1Android専用のJavaコンパイラで、直接dexファイルを出力できます。ただし、Jackはまだannotation processingをサポートしていないなどの制限があるため、実際のアプリケーションで採用するのは難しいでしょう。正規版までにannotation processingサポートが入るといいのですが。

ところで現在すでにRetrolambdaで一部のJava8構文が使えます。Retrolambdaを採用したプロジェクトはすでにいくつかありますし、NとRetrolambdaを比較検討したいところです。

よって、考慮すべきは「ビルドがN SDKかJackかRetrolambdaか」の3パターン、実行環境としては、古いAndroid OSの代表として「ICS」、そして「N」の2パターン、この2つの組み合わせで考える必要があります。

それぞれで、Java8の構文とクラスライブラリの幾つかをピックアップして使用可能かどうかを表にしてみました。

※ Nはpreview-1版であり、正規版では結果は異なります。minSdkVersion=14が効かない問題があり、動作はさせていません。下記の表は単なるビルドの成否などから推定している部分もあります。

N SDK x ICS runtime N SDK x N runtime Jack x ICS runtime Jack x N runtime Retrolambda x ICS runtime Retrolambda x N runtime
lambda expressions no no yes yes yes yes
default interface methods no no yes yes yes yes
static methods on interfaces no no yes yes yes yes
repeatable annotations no no yes yes yes yes
optional no no no no no no
java.util.function.* no yes* no yes no yes
java.util.stream.* no no no no no no
  • Java7モードでビルドしてlambda式などを使わずにjava.util.function.* を使用することだけならできます。

純正のN SDKだとほとんど何も使用できませんが、これはN SDKのdexコマンドがJava8用に出力されたクラスライブラリのバージョン(52)を処理できないためです。

なおいくつかのAOSPのクラスをOpenJDK7 / OpenJKD8と比較したところ*2、基本的にはOpenJDK7をベースとしており、 List#forEach() などの一部のメソッドのみOpenJDK8から移植しているようです。

以上を踏まえると、Android N preview-1で使えるJava8は「Java 7.5」ともいうべき中途半端な状態ですね。もちろん正規版が近づいたらまた状況は変わるかもしれないので、あくまでも「N preview-1では」ということですが。

そしてクラスライブラリ以外の新構文は、実はNとは関係ありません。First Preview of Android N: Developer APIs & Toolsのエントリでも、Jackで提供される言語機能はGingerbread (Android 2.3)でも使えると書いてあります。このあたりをまとめて「NでJava8をサポート」と発表するのは開発者に混乱を招くのでやめていただきたいですね。

関連エントリ