2016-12-30 21 views
3

私は、両方のput操作が次のコードでNullPointerExceptionをスローすることが予想されますが、実際にはラムダ式はうまく動作し、メソッド参照だけがNPEをスローします。メソッド参照とラムダの違い

public static void main(String... args) { 
    Object object = null; 
    Map<String, FuncInterface> map = new HashMap<>(); 

    map.put("key1",() -> object.notify()); // works 
    map.put("key2", object::notify);   // throws NPE 
} 

@FunctionalInterface 
private interface FuncInterface { 
    public void someAction(); 
} 

どういう違いがありますか?

+0

あなたのコードを試しましたが、どちらの場合もNPEを取得しました。 –

+0

@ SunilSinghBoraあなたはeclipseを使用していますか? – assylias

+0

はい。 Eclipse IDEでこのコードを実行しています。 –

答えて

6

ラムダは呼び出されたときに評価されます:map.get("key1").someAction()を呼び出した場合は、NPEを取得します。

メソッド参照は、作成時に評価されます。つまり、最初にobject::notifyと書くと、NPEをすぐにスローします。特に

the JLS 15.13.3状態:

方法基準発現の評価方法自体の呼び出しから区別されます。
最初に、メソッド参照式がExpressionNameまたはPrimaryで始まる場合、この部分式が評価されます。サブ式がnullに評価されると、NullPointerExceptionが発生し、メソッド参照式が突然完了します。

+0

Javaに迂回する.NET開発者はいらっしゃいませんが、オブジェクトは最後にマークされていないので、最初にルールをコンパイルすることはできますが(実際にオブジェクトを割り当てても、あなたが最後のObjectオブジェクトにインスタンスを割り当てていないときは、ヌル参照について);-)編集:ああ、「効果的に最終的な」ことについて何かでなければならない。気にしないで。 – VolkerK

+0

私はあなたの質問を完全に理解していますが、コンパイラはヌルチェックを行いません。 'Object o = null;を書くことができます。あなたが望むなら、それはコンパイルされます:o.toString(); ' – assylias

+0

'Object object = null'を' Object object = new Object() 'に変更すると、コンパイラはオブジェクトがラムダで最終的ではないと不満を持ちます。一方、finalとマークしても 'null 'のままにしておくと、コンパイラは' object :: notify'、つまりnull :: notifyについて文句を言うことはありません。しかし、はい、私はコンパイラが "効果的に最終的に"チェックした "質問"を投稿した後に気づいたので、最初の考え方と矛盾した動作ではありません。 – VolkerK

関連する問題