50

よくわかりません。Java 8 が石器時代から出現し、ラムダ/クロージャのサポートを開始すると思っていました。しかし、私がこれを試すと:

public static void main(String[] args) {
    int number = 5;

    ObjectCallback callback = () -> {
        return (number = number + 1);
    };

    Object result = callback.Callback();
    System.out.println(result);
}

…と書いてありnumber should be effectively finalます。それは、閉鎖ではないと思います。それは、参照ではなく値によって環境をコピーしているように聞こえます。

ボーナス質問!

Android は Java 8 機能をサポートしますか?

4

5 に答える 5

43

なぜ、なぜ、ジャバ。なぜああなぜ。

本当の答えを得るには、関連する Oracle Java チーム メンバーと長い (プライベートな) ディスカッションを行う必要があります。(彼らがあなたと話してくれるなら...)


しかし、これは下位互換性とプロジェクト リソースの制約の組み合わせによるものだと思います。そして、現在のアプローチが実用的な観点から「十分に良い」という事実。

プロシージャ コンテキストをファーストクラス オブジェクト (つまり、クロージャ) として実装するには、特定のローカル変数の有効期間が、宣言するメソッド呼び出しの戻りを超えて延長される必要があります。つまり、それらをスタックに置くことはできません。代わりに、一部のローカル変数をヒープ オブジェクトのフィールドにする必要がある状況になります。つまり、新しい種類の隠しクラスまたは JVM アーキテクチャの根本的な変更が必要です。

このようなことを実装することは技術的に可能ですが、Java 言語は「グリーン フィールド」言語ではありません。Java で「本当のクロージャー」をサポートするために必要な性質の変更は困難です。

  • すべてのツール チェーンを更新するには、オラクルおよびサード パーティの実装者が多大な労力を費やすことになります。(そして、コンパイラについて話しているだけではありません。デバッガ、プロファイラ、難読化ツール、バイトコード エンジニアリング フレームワーク、永続化フレームワークなどがあります。)

  • 次に、これらの変更の一部が、既存のデプロイされた何百万もの Java アプリケーションの下位互換性に影響を与えるリスクがあります。

  • 何らかの方法で JVM を利用する他の言語などに影響を与える可能性があります。たとえば、Android は、Davlik ツールチェーンの「入力言語」として JVM アーキテクチャ/バイトコード ファイルに依存しています。Python、Ruby、および JVM プラットフォーム用にコードを生成するさまざまな関数型言語の言語実装があります。


要するに、Java での「本当のクロージャ」は、関係者全員にとって非常に恐ろしい提案です。「決勝戦の閉鎖」ハックは、機能する実用的な妥協案であり、実際には十分です。

final最後に、将来の版で制限が取り除かれる可能性は常にあります。(息は止めませんが・・・)


Android は Java-8 機能をサポートしますか?

信頼できる内部情報を持っていない限り、それは答えられません。もしそうなら、彼らはここでそれを明らかにすることに夢中になるでしょう. 確かに、Google は Java 8 のサポートを発表していません。

しかし、幸いなことに、Java 7 構文拡張機能が現在、KitKat および対応するバージョンの Android Studio または Eclipse ADT でサポートされています。

于 2013-06-20T03:05:28.100 に答える
1

最終参照を使用して、外側のスコープで宣言された変数の状態の変更を回避できますが、結果は同じままで、クロージャーの外側のスコープの状態は保持されず、(最終参照によって) 参照されるオブジェクトへのさらなる変更は、クロージャーに見られます。

@Test
public void clojureStateSnapshotTest() {
    Function wrapperFunc;
    wrapperFunc = (a) -> {
        // final reference
        final WrapLong outerScopeState = new WrapLong();

        outerScopeState.aLong = System.currentTimeMillis();
        System.out.println("outer scope state BEFORE: " + outerScopeState.aLong);

        Function closure = (b) -> {
            System.out.println("closure: " + outerScopeState.aLong);
            return b;
        };

        outerScopeState.aLong = System.currentTimeMillis();
        System.out.println("outer scope state AFTER: " + outerScopeState.aLong);

        // show correct snapshot state
        closure.apply(new Object());

        return a;
    };
    // init clojure
    wrapperFunc.apply(new Object());
}

public class WrapLong {
    public long aLong = 0;
}

それでも楽しい...

于 2014-02-13T17:21:06.003 に答える