2014-07-15 3 views
12

익명 클래스 대신 람다를 사용하도록이 코드를 리팩토링하려고합니다. GUI의 간단한 항목 목록입니다. 각 항목마다 다른 청취자를 등록하고 마지막으로 생성 된 항목은 클릭 할 때 특별한 작업을 수행합니다.익명 클래스를 람다로 변환 한 후에 코드가 달라집니다.

class ItemList { 
    interface OnClickListener { 
     void onClick(); 
    } 
    OnClickListener current; 
    OnClickListener newListener(final int n) { 
     return current = new OnClickListener() { 
      public void onClick() { 
       if (this == current) 
        System.out.println("doing something special (item #"+n+")"); 
       System.out.println("selected item #" + n); 
      } 
     }; 
    } 
    public static void main(String[] args) { 
     ItemList l = new ItemList(); 
     OnClickListener ocl1 = l.newListener(1); 
     OnClickListener ocl2 = l.newListener(2); 
     OnClickListener ocl3 = l.newListener(3); 
     ocl1.onClick(); 
     ocl2.onClick(); 
     ocl3.onClick(); 
    } 
} 

이 예상대로 작동합니다

$ javac ItemList.java && java ItemList 
selected item #1 
selected item #2 
doing something special (item #3) 
selected item #3 

지금 내가 대신 익명 클래스의 람다 사용하도록 변경 :

class ItemList { 
    interface OnClickListener { 
     void onClick(); 
    } 
    OnClickListener current; 
    OnClickListener newListener(final int n) { 
     return current =() -> { 
      if (this == current) 
       System.out.println("doing something special (item #"+n+")"); 
      System.out.println("selected item #" + n); 
     }; 
    } 
    public static void main(String[] args) { 
     ItemList l = new ItemList(); 
     OnClickListener ocl1 = l.newListener(1); 
     OnClickListener ocl2 = l.newListener(2); 
     OnClickListener ocl3 = l.newListener(3); 
     ocl1.onClick(); 
     ocl2.onClick(); 
     ocl3.onClick(); 
    } 
} 

를하지만 이제 더 이상 마지막에 특별한 일을하지 않습니다 목? 왜? ==은 람다와 다르게 작동합니까? 처음에는 retrolambda의 버그라고 생각했지만이 예제는 일반 JDK8에서 실행 중이며 여전히 발생합니다. 람다 내부

$ javac A.java && java A 
selected item #1 
selected item #2 
selected item #3 
+1

Lambdas는 실제로 본문에서 'this'를 참조 할 수 없습니다. –

답변

12

this은 익명의 클래스 인스턴스 내부에 this와 같은 의미하지 않는다.

lambda 안에는 둘러싼 클래스가 들어 있습니다.

... 람다 식은 새로운 수준의 범위 지정을 도입하지 않습니다. 따라서 둘러싸는 범위의 필드, 메서드 및 로컬 변수에 직접 액세스 할 수 있습니다. ... 둘러싼 클래스의 변수에 액세스하려면 this 키워드를 사용하십시오. 그 방법은 물체 - ... 익명 클래스의 인스턴스 내부

그것이 현재 오브젝트 인스턴스 메소드 또는 생성자 내

지칭이 현재 오브젝트에 대한 참조는 이 유형 OnClickListener의 람다 식으로 클래스 ItemList의 인스턴스를 비교하기 때문에 또는 생성자는 람다 식에, this == current 결코 사실 이유

라고되고있다.

+0

왜 현재 == 이것이 결코 사실이 아닌지 아직 확실하지 않습니다. 클래스를 감싸는 클래스가 동일하기 때문에 우리는 출력에서 ​​세 가지 "무언가"를보아야합니다. –

+0

@OlegGryb 엔 클로징 클래스는 ItemList이므로 현재 (OnClickListener 유형의 람다 식)와 결코 같지 않습니다. – Eran

+0

맞아요, 생각하지 않으 셨습니다. 그래서 current.onClick()을이 방법으로 사용하려면 여전히 작동해야합니다. –

관련 문제