Answers:
棘轮怪胎的答案及其注释线程中存在相当多的错误信息。由于评论太小,我将在此处回答。另外,由于毕竟这是一个答案,所以我也将尝试回答原始问题。(但是请注意,我不是类型系统方面的专家。)
首先,对原始问题的简短回答是“是”和“否”。是的,Java 8的类型推断要比Java 7大得多,并且,不,Java 8中没有“新”类型系统,尽管有一些细微的变化。
Java 8仍将是静态类型的,并且在类和接口之间仍然存在二分法。没有新类型,例如函数类型。Lambda的类型实质上是“功能接口”,它是具有单个抽象方法的普通接口。
接口现在可以具有默认方法形式的代码,但是类的单继承和接口的多重继承的模型保持不变。当然,有一些调整,例如在存在默认方法的情况下用于方法解析的规则,但是基本原理没有变化。
通过类型推断推断出的任何类型都可以显式地写出。以棘轮怪胎为例,
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表达式不是语法糖。Ratchet freak声明将lambda表达式转换为匿名内部类实例化,Sparkleshy只是简单地断言lambda 是匿名内部类的语法糖,但是这些语句是错误的。它们可能基于过时的信息。早期的lambda实现确实以这种方式实现了lambda,但是情况已经发生了变化。
Lambda表达式在语义上与内部类不同,并且在实现方式上与内部类不同。
Lambda表达式在语义上与内部类有所不同。评估lambda表达式不必每次都创建一个新实例。他们也有不同的捕获语义,例如,他们抓住这个不同。在内部类中,这是内部类实例,而在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 lambda构建(我使用b69)中,输出将类似于以下内容:
CaptureThis$1@113de03
outer
此外,lambda表达式的实现与内部类完全不同。如果比较反汇编的输出,您会看到内部类代码直接编译为创建并调用CaptureThis $ 1的构造函数,而lambda表达式编译为invokedynamic指令,该指令通过未指定的方式获取Runnable。有关其工作原理和原因的完整说明,请参见Brian Goetz在JavaOne 2012上发表的演讲Lambda:深入了解。
this
带MyClass.this