2017-02-27 2 views
8

匿名クラスとラムダ式の異なる動作とちょっと混乱します。匿名クラスとラムダ式の "this"の値

私はラムダ式を使用しています:

//Test.java 

Runnable r1 =() -> System.out.println(this); 
Runnable r2 =() -> System.out.println(toString()); 

@Override 
public String toString() { 
    return "Hello World!"; 
} 

// in main method 
new Test().r1.run(); 
new Test().r2.run(); 
Output : Hello World! 
     Hello World! 

匿名クラス使用:

Runnable r1 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(this); 
    } 
}; 

Runnable r2 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(toString()); 
    } 
}; 

@Override 
public String toString() { 
    return "Hello World!"; 
} 

// in main method 
new Test().r1.run(); 
new Test().r2.run(); 
Output : [email protected] 
     [email protected] 

誰かが別の動作を説明していただけますか?

答えて

10

ラムダ式では、thisが周囲のクラスに字句的にバインドされていますが、匿名クラスでは匿名クラスに字句的にバインドされています。

Java言語仕様が15.27.2でこの動作を説明します。匿名クラスの宣言、名前の意味とラムダ本体に登場thissuperキーワードに出現するコードとは異なり

は、参照の接近に伴い宣言は、周囲のコンテキストと同じです(ただし、ラムダパラメータに新しい名前が追加されます)。

ラムダ式の本体で透明度が0,233,(明示的および暗黙的)であることは、周囲のコンテキストと同じ扱いであるため、実装の柔軟性が増し、修飾されていない名前の意味が身体は過負荷解決に依存しない。

は、実際に物事を参照するために名前を使用するために、より一般的である一方、ラムダ式は、(どちらか自分自身を再帰的に呼び出すためか、他のメソッドを呼び出すために)自分自身について話をする必要がありますすることは珍しくあり、話します(this,)を囲むクラス内に追加する必要があります。ラムダ式が自身を参照する必要がある場合は(this経由)、代わりにメソッド参照または匿名の内部クラスを使用する必要があります。

匿名クラス内部から周囲のクラスのthisを参照するには、qualified thisを使用する必要があります。

Runnable r1 = new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(Test.this); // or Test.this.toString() 
    } 
}; 
+0

答え:ありがとうございます。しかし、字句的に何が結ばれていますか? –

+2

@MehrajMalikこれは、それらが見つかったコンテキストに基づいてコンパイル時にバインドされていることを意味します。 – 4castle

+3

これは 'this'と' super'に影響するだけではありません。匿名の内部クラスの内部では、継承されたメンバ( 'toString()'だけでなく)があるかもしれませんが、ラムダ式は機能インタフェースから何も継承しません。 – Holger