web-dev-qa-db-ja.com

Java 8の型推論

Java 8の新しいラムダ記法の導入(たとえば この記事 を参照)は、何らかの型推論を必要とするでしょうか?

もしそうなら、新しい型システムはJava言語全体にどのように影響しますか?

30
Giorgio

ratchet freak's answer とコメントスレッドにかなりの不正確な情報があります。コメントが小さすぎるので、こちらで回答します。また、答えは結局のところ、元の質問にも答えようと思います。 (ただし、私は型システムの専門家ではありません。)

まず、元の質問に対する短い回答は「はい」と「いいえ」です。はい、Java 8はJava 7よりも型推論がかなり多く、いいえJava 8の「新しい」型システムではありませんが、いくつかのマイナーな変更があります。

Java 8は静的に型付けされたままであり、クラスとインターフェースの間で二分されます。関数型などの新しい型はありません。ラムダのタイプは、本質的には単一の抽象メソッドを持つ通常のインターフェースである「関数型インターフェース」です。

インターフェースはデフォルトのメソッドの形式でコードを持つことができますが、クラスの単一継承とインターフェースの多重継承のモデルは同じままです。もちろん、デフォルトのメソッドが存在する場合のメソッド解決のルールなど、いくつかの調整がありますが、基本は変更されていません。

型推論によって推論される型はすべて明示的に書き出すことができます。 ratchet freak の例を使用するには、

Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });

基本的に砂糖です

Collections.<MyClass>sort(list,
    (Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));

したがって、 sparkleshy の「型推論は型システムの拡張を必要としない」というステートメントは基本的に正しいです。

しかし、構文糖質に戻るために、ラムダ式は匿名の内部クラスの構文糖質ではないという私の声明を繰り返します。ラチェットフリークはラムダ式が翻訳されていると述べました匿名の内部クラスのインスタンス化に含まれ、Sparkleshyは匿名の内部クラスのラムダis構文糖を単純に再アサートしましたが、これらのステートメントは正しくありません。それらはおそらく古い情報に基づいています。初期のラムダ実装はこのようにラムダを実装していましたが、状況は変わりました。

ラムダ式は、意味的に内部クラスとは異なり、内部クラスとは異なる方法で実装されます。

ラムダ式は、いくつかの点で内部クラスと意味的に異なります。ラムダ式の評価では、毎回新しいインスタンスを作成する必要はありません。また、キャプチャのセマンティクスも異なります。たとえば、thisのキャプチャ方法は異なります。内部クラスでは、thisは内部クラスインスタンスですが、ラムダでは、thisは外側のインスタンスです。以下を検討してください。

public class CaptureThis {
    void a(Runnable r) { r.run(); }

    void b() {
        a(new Runnable() { public void run() { System.out.println(this); }});
        a(() -> System.out.println(this));
    }

    public String toString() { return "outer"; }

    public static void main(String[] args) { new CaptureThis().b(); }
}

最近のJDK 8ラムダビルド(私は b69 を使用しました)では、出力は次のようになります。

CaptureThis$1@113de03
outer

さらに、ラムダ式は内部クラスとはまったく異なる方法で実装されます。逆アセンブルされた出力を比較すると、内部クラスコードは作成に直接コンパイルされ、CaptureThis $ 1のコンストラクターを呼び出しますが、ラムダ式は、Runnableを未指定の手段で取得するinvokedynamic命令にコンパイルされます。これがどのように機能するか、またその理由の詳細については、Brian GoetzのJavaOne 2012の講演 Lambda:A Peek Under the Hood を参照してください。

47
Stuart Marks