2016-06-22 6 views
8

私は、Javaラムダとメソッド参照の動作についてちょっと混乱しています。 。元のために、私たちはこのコードを持っている:静的なフィールドの値をキャプチャするとき、同等のラムダ式とメソッド参照が異なる動作をするのはなぜですか?

import java.util.function.Consumer; 

public class Main { 

    private static StringBuilder sBuilder = new StringBuilder("1"); 

    public static void main(String[] args) { 
     Consumer<String> consumer = s -> sBuilder.append(s); 
     sBuilder = new StringBuilder("2"); 
     consumer.accept("3"); 
     System.out.println(sBuilder); 
    } 

} 

出力:

23 

この私たちが代わる場合に予想されるように動作しますが、

S - > sBuilder.append(S)

sB uilder ::

追加出力は次のようになります。

2 

はどのようにこれを説明するために、あなたに任意のアイデアをお持ちですか?これは同じものではありませんか?ありがとう。

+1

[この](http://stackoverflow.com/questions/30514995/what-is-the-difference-between-a-lambda-and-a-method-reference-at-aです-runtime-leve)も複製用に畳み込まれていますか? –

+0

@SotiriosDelimanolis少し参考になりました。参考にしていただきありがとうございます。 – j2esu

答えて

10

ラムダ式では、sBuilderフィールドはキャプチャされますが、評価されません。これは、対応する関数インタフェースメソッドが呼び出されたときにのみ評価されます。 sBuilderメソッドリファレンスに

sBuilder = new StringBuilder("2"); 

で作成し、フィールドに割り当てられた新しいインスタンスを参照し、その時点で、sBuilderフィールドはConsumerインスタンスを生成するために直ちに評価されます。この値は、静的初期化子

private static StringBuilder sBuilder = new StringBuilder("1"); 

で作成されたインスタンスを参照してConsumerはその1つの上で動作します。あなたは新しいものを印刷します。

形態である場合に次のようRun-Time Evaluation of Method References

に関する呼び出しメソッドの本体は、方法 基準表現の形式に依存するJava言語仕様から


ExpressionName :: [TypeArguments] Identifierまたは Primary :: [TypeArguments] Identifierの場合、 呼び出しメソッドの本体は、 のメソッド呼び出し式の影響を受けます。コンパイル時の宣言であるile-time宣言は、 のメソッド参照式です。呼び出しモードは、コンパイル時に由来する

  • :§15.12.4.3、§15.12.4.4、及び §15.12.4.5、で指定されるように方法 呼出し式の実行時の評価であります§15.12.3で規定されている宣言。

  • 方法基準発現が 評価されたとき決定される目標基準は、ExpressionName又はPrimaryの値です。

  • メソッド呼び出し式の引数は、呼び出しメソッドの仮パラメータです。

+1

言い換えれば、 's - > sBuilder.append(s)'は 's - > Main.sBuilder.append(s)'と同等です。 sBuilder :: append'は 'StringBuilder temp = Main.sBuilder;と同じです。 s - > temp.append(s) ' –

+1

@ TavianBarnesあなたはそれを編集することができます。 –

+0

好奇心の疎外さから、最初はコミュニティウィキとしてマークするのはなぜですか? –

関連する問題