Java Lambdas和闭包
我听说lambdas即将到达你身边的Java(J8)。 我找到了他们在某个博客上看起来像什么的例子:
SoccerService soccerService = (teamA, teamB) -> {
SoccerResult result = null;
if (teamA == teamB) {
result = SoccerResult.DRAW;
}
else if(teamA < teamB) {
result = SoccerResult.LOST;
}
else {
result = SoccerResult.WON;
}
return result;
};
所以马上蝙蝠:
teamA
和teamB
在哪里键入? 或者他们不是(像一些奇怪的泛型)? Lambda表达式只是实现目标接口的语法糖,这意味着您将通过lambda表达式在接口中实现特定的方法。 编译器可以推断出接口中参数的类型,这就是为什么你不需要在lambda表达式中显式定义它们的原因。
例如:
Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);
在这个表达式中,lambda表达式显然实现了一个字符串Comparator
,因此,这意味着lambda表达式是用于实现compare(String, String)
语法糖。
因此,编译器可以安全地假定s1
和s2
的类型是String
。
您的目标接口类型提供编译器需要确定什么是lambda参数的实际类型的所有信息。
Oracle Corportion的Java语言架构师Briant Goetz在JDK 8 Lambdas上发表了一些正在进行的工作文章。 我相信你的问题的答案在那里:
这第二篇文章解释了如何在字节码级别实现lambda表达式,并可能帮助您深入研究第二个问题的细节。
请参阅本页以获得该示例的完整版本(但是,相关部分如下所示)。
这些类型是从SoccerService接口和SoccerResult枚举中推断出来的,不会显示在您的代码片段中:
enum SoccerResult{
WON, LOST, DRAW
}
interface SoccerService {
SoccerResult getSoccerResult(Integer teamA, Integer teamB);
}
(lambdas与标准匿名类的好处)只是减少了冗长:
(x, y) => x + y
对比如:
new Adder()
{
public int add(int x, int y)
{
return x + y;
}
}
对于闭包和lambda之间的区别,请参阅此问题。
Lambda的使用目标类型,就像通用方法调用(自1.5)和钻石[不是]运算符(自1.7)一样。 粗略地说,应用了结果的类型用于提供单一抽象方法(SAM)基本类型的类型以及方法参数类型的类型(或可以推断)。
作为1.5中通用方法推断的一个例子:
Set<Team> noTeams = Collections.emptySet();
1.7中的钻石操作员:
Set<Team> aTeams = new HashSet<>();
团队,团队,团队,团队,团队,团队。 我甚至爱说这个词团队。
lambda是一种有限的闭包形式,几乎和匿名内部类一样,但是有一些随机差异可以吸引你:
外this
不被内隐藏this
。 这意味着在一个lambda和一个匿名内部类中的相同文本可能意味着微妙但完全不同的东西。 这应该让Stack Overflow忙于奇怪的问题。
为了弥补缺乏内在this
,如果直接分配到一个局部变量,则该值是拉姆达中访问。 IIRC(我可以检查,但不会),在一个匿名的内部类中,本地将处于作用域中,并将变量隐藏在外部作用域中,但不能使用它。 我相信缺少一个实例初始化程序使得这更容易指定。
本地字段不会被标记为final
但可能会被视为final
。 所以不是他们在范围内,但你实际上可以阅读(尽管不写)他们。
简短的语法。 就是这样。
当然,其余的Java语法也像以前一样绝望。
我不认为这是在最初的实现中,而是作为[inner]类实现,而lambda可以使用方法句柄。 方法句柄的性能比之前的预测要差一些。 抛弃类,应该减少字节码的占用空间,可能的运行时间占用空间以及确定的类加载时间。 可能有一个实现,大多数匿名内部类(不是Serializable
,简单的静态初始化程序)没有经过构思不佳的类加载机制,没有发现任何特别明显的不兼容性。
(希望我知道正确的术语。)
链接地址: http://www.djcxy.com/p/51285.html