2017-02-27 11 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이 주변 클래스에 어휘 적으로 바인딩되는 반면 익명 클래스에서는 익명 클래스에 어도비 바인딩되어 있습니다. this은 익명 클래스에 어휘 적으로 바인딩됩니다.

Java 언어 사양은 15.27.2에서이 동작을 설명 : 익명 클래스 선언에 나타나는 코드와는 달리

, 이름의 의미와 참조의 접근과 함께, 람다 본문에 나타나는 thissuper 키워드 선언문은 주변 환경과 동일합니다 (람다 매개 변수가 새로운 이름을 도입한다는 것을 제외하고).

λ 표현의 본문에서 투명도가 this (명시 적이든 암시 적이든) - 즉 주변 환경과 동일하게 취급 됨 - 구현시 유연성이 향상되고 다음과 같은 경우에 규정되지 않은 이름의 의미가 금지됩니다. 시체가 과부하 해결에 의존하지 않습니다.

는 실질적으로 사물을 참조하는 이름을 사용하려는 일반적인 반면 람다 표현식 (중 자신을 재귀 적으로 호출하는 또는 다른 방법을 호출) 자체에 대해 이야기해야하는 것은 이례적인 일이다, 말하기 그렇지 않으면 섀도 잉 된 둘러싸는 클래스에서 (this, toString()). 람다 표현식이 자신을 참조해야하는 경우 (예 : 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