600000007

プログラムと折り紙のブログです。

Java8のLambdaの型推論が実行時にならいと型が分からない理由(追記あり)

JJUGナイトセミナー「Inside Lambda」に参加してきました。
Java8のLambdaの概要と、実装方法についてのお話でした。
非常に面白かったのですが、その中でLambdaの型推論が実行時にならいと型が分からないという話があったのでまとめてみます。

Lambdaの型推論

Lambda式の中ではコンパイラが推測できる場合は型を省略する事が可能です。

Comparator<Integer> comp = (x , y) -> x -y;

しかし、実際に型が決まるのはコンパイル時ではなく実行時になります。
それはなぜでしょうか?

Lambdaの実装

その答えは、ナイトセミナーの宮川さんの発表で理解できました。
それは、Lambdaがinvokedynamicを使って実装されているからです。
invokedynamicについては・・・これまた宮川さんの資料が分かりやすいです。
私の理解では、

  • JVMで実際にメソッドを実行したりするのがInvokeなんたらのお仕事
  • その中でもinvokedynamicはJava以外の動的型付け言語をJVMで動かすための機能
  • そのためinvokedynamicは実行中にクラスファイルを動的に生成したりできる

という感じです。
で、Java8のLambdaはinvokedynamicを使って実装されているそうです。
そのため、実際に型が分かるのが実行時ということになります。

仕様?

実装がたまたまそうなっている、という話だそうです。
なのでJava8が正式リリースされた時には、ひょっとしたらコンパイル時に型が決まるようになっているかもしれませんね。

実害はあるのか?

ちょっと考えてみたのですが思いつきませんでした。
実行時に決まるからどんな型になるかわからない?!って事はないですよね、これ。
あくまでコンパイラも型推論チェックをやっているので、実際に予期せぬ型になってしまうことはなさそうです。

まとめ

Scalaを使おう!

追記


きしださんからコメントをもらいました。


というわけで、正確には「ラムダ式の型は実行時にならないと決まらない」という話でした。
タイトルも含めて書き直そうかとも思ったのですが、きしださんにコメントもらえた記念ということで追記だけにしておきます。