답변:
래칫 괴물의 답변 과 주석 스레드 에는 잘못된 정보가 많이 있습니다. 댓글이 너무 작기 때문에 여기에 답변 해 드리겠습니다. 또한 이것은 결국 답변이므로 원래 질문에도 대답하려고합니다. (그러나 나는 타입 시스템 전문가가 아닙니다.)
첫째, 원래 질문에 대한 짧은 대답은 예와 아니오입니다. 예, Java 8은 Java 7보다 상당히 많은 유형 유추를 갖습니다. 아니요, 약간의 변경 사항이 있지만 Java 8에는 "새로운"유형 시스템이 없습니다. .
Java 8은 여전히 정적으로 입력되며 클래스와 인터페이스 사이에 이분법이 있습니다. 함수 유형과 같은 새로운 유형은 없습니다. 람다의 유형은 본질적으로 하나의 추상적 인 방법을 가진 일반적인 인터페이스 인 "기능적 인터페이스"이다.
인터페이스는 이제 기본 메소드 형태의 코드를 가질 수 있지만 클래스의 단일 상속 모델과 여러 인터페이스의 상속 모델은 동일하게 유지됩니다. 물론 기본 메소드가있는 경우 메소드 분석 규칙과 같은 일부 조정이 있지만 기본 사항은 변경되지 않습니다.
형식 유추로 유추되는 모든 형식은 명시 적으로 작성할 수 있습니다. 래칫 괴물 의 예 를 사용하려면
Collections.<MyClass>sort(list, (a, b) -> { return a.order - b.order; });
기본적으로 설탕입니다
Collections.<MyClass>sort(list,
(Comparator<MyClass>)((MyClass a, MyClass b) -> { return a.order - b.order; }));
따라서 sparkleshy 의 진술 "유형 추론은 유형 시스템의 확장이 필요하지 않습니다"는 기본적으로 정확합니다.
그러나 구문 설탕으로 돌아 가기 위해 람다 표현이 익명의 내부 클래스의 구문 설탕이 아니라는 진술을 반복 합니다. 래칫 괴물은 람다 표현이 익명의 내부 클래스 인스턴스화로 번역되었다고 스파클시는 단순히 람다 가 익명의 내부 클래스에 대한 구문 설탕 이라고 단언 했지만, 이러한 진술은 틀렸다. 오래된 정보를 기반으로합니다. 초기 람다 구현은 이런 식으로 람다를 구현했지만 상황이 변경되었습니다.
Lambda 식은 내부 클래스와 의미 적으로 다르며 내부 클래스와 다르게 구현됩니다.
람다 식은 몇 가지면에서 내부 클래스와 의미 적으로 다릅니다. 람다 식을 평가할 때마다 새 인스턴스를 만들 필요는 없습니다. 또한 서로 다른 캡처 의미론을 가지고 있습니다. 예를 들어, 이들은 다르게 캡처 합니다 . 내부 클래스에서, 이는 람다있는 반면, 내부 클래스 인스턴스 이것은 둘러싸 인스턴스이다. 다음을 고려하세요:
public class CaptureThis {
void a(Runnable r) { r.run(); }
void b() {
a(new Runnable() { public void run() { System.out.println(this); }});
a(() -> System.out.println(this));
}
public String toString() { return "outer"; }
public static void main(String[] args) { new CaptureThis().b(); }
}
최근 JDK 8 람다 빌드 ( b69 사용 )에서 출력은 다음과 같습니다.
CaptureThis$1@113de03
outer
또한 람다 식은 내부 클래스와 완전히 다르게 구현됩니다. 디스 어셈블 된 출력을 비교하면 내부 클래스 코드가 생성으로 직접 컴파일되고 CaptureThis $ 1의 생성자를 호출하는 반면 람다 식은 지정되지 않은 수단을 통해 Runnable을 조달하는 invokedynamic 명령으로 컴파일됩니다. 작동 방식 및 이유에 대한 자세한 설명은 Brian Goetz의 JavaOne 2012 talk Lambda : A Peek Under The Hood를 참조하십시오 .
this
으로MyClass.this