Java 中的闭包——三大提案之间的语法差异?
Posted
技术标签:
【中文标题】Java 中的闭包——三大提案之间的语法差异?【英文标题】:Closures in Java - syntax differences between the three major proposals? 【发布时间】:2009-11-25 18:57:19 【问题描述】:已经提出了将closures 添加到Java 语言的三个主要建议:
BGGA (Bracha Gafter Gosling Ahé) 也称为“完全关闭”,作者是 Gilad Bracha、Neal Gafter、James Gosling 和 Peter von der Ahé CICE (Concise Instance Creation Expressions) 也称为“简化内部类”,作者 Bob Lee、Doug Lea 和 Josh Bloch FCM (First Class Methods),作者:Stephen Colebourne 和 Stefan Schulz我的问题:
三个提案(BGGA、CICE 和 FCM)在语法上有何区别?【问题讨论】:
来吧 - 您提供了提案的链接并且无法比较差异?所有提案都在一开始就提供了示例... 我认为这是一个有效的问题。有些人可能有一些普通读者会错过的洞察力。 +1 -- 我曾想过(和其他人一样 :-) JDK7 闭包已经死了...... @Jason S:就在本周,Sun 出人意料地宣布闭包将出现在 Java 7 中,但这将是一个新版本,而不是当前的三个提议之一. 出于好奇:您为什么对提案之间的句法差异如此感兴趣?语义差异不是更重要吗?我的意思是,如果存在一些语义限制,一开始就禁止您使用闭包,那么使用方括号与花括号作为闭包分隔符有什么好处? 【参考方案1】:This IBM paper 给出了 BGGA 和 CICE 之间语法差异的很好的例子:
BGGA 提案
BGGA 提案创建了函数类型的概念,其中函数具有类型化参数列表、返回类型和 throws 子句。在 BGGA 提案中,平方和代码类似于清单 9 中的代码:
清单 9。使用 BGGA 闭包语法计算平方和
sumOfSquares = mapReduce(myBigCollection,
Double x => x * x ,
Double x, Double y => x + y );
=> 符号左侧大括号内的代码标识参数的名称和类型;右边的代码表示正在定义的匿名函数的实现。此代码可以引用块中定义的局部变量、闭包的参数或创建闭包的范围内的变量。
在 BGGA 提案中,您可以将变量、方法参数和方法返回值声明为函数类型。您可以在任何需要单个抽象方法类(如 Runnable 或 Callable)实例的上下文中提供闭包;对于匿名类型的闭包,提供了一个 invoke() 方法,因此您可以使用指定的参数列表调用它们。
BGGA 提案的主要目标之一是允许程序员创建类似于控制结构的方法。因此,BGGA 还提出了一些语法糖,允许您调用接受闭包的方法,就好像它们是新关键字一样,这样您就可以创建 withLock() 或 forEach() 之类的方法并像控制原语一样调用它们。清单 10 显示了如何在 BGGA 提案下定义 withLock() 方法;清单 11 和清单 12 显示了如何使用标准形式和“控制构造”形式来调用它:
清单 10。在 BGGA 闭包提案下编写 withLock() 方法
public static <T,throws E extends Exception>
T withLock(Lock lock, =>T throws E block) throws E
lock.lock();
try
return block.invoke();
finally
lock.unlock();
清单 10 中的 withLock() 方法接受锁和闭包。闭包的返回类型和 throws 子句是泛型参数;编译器中的类型推断通常允许在不指定 T 和 E 的值的情况下调用它,如清单 11 和清单 12 所示:
清单 11。调用 withLock()
withLock(lock, =>
System.out.println("hello");
);
清单 12。使用控件构造简写调用 withLock()
withLock(lock)
System.out.println("hello");
与泛型一样,BGGA 提案下的闭包的大部分复杂性由库创建者承担;使用接受闭包的库方法要简单得多。
BGGA 提案还用于修复在尝试使用内部类实例来获得闭包好处时出现的一些透明性故障。例如,return、break 和 this 在代码块中的语义与在表示同一代码块的 Runnable(或其他内部类实例)中的语义不同。在迁移代码以利用通用算法时,这些不透明元素可能会导致混淆。
CICE 提案
CICE 提案是一个更简单的提案,它解决了实例化内部类实例过于繁琐的问题。它没有创建函数类型的概念,而是创建了一种更紧凑的语法,用于使用单个抽象方法(例如 Runnable、Callable 或 Comparator)来实例化内部类的实例。
清单 13 显示了 CICE 下平方和代码的样子。它明确了 mapReduce() 使用的 UnaryFunction 和 BinaryFunction 类型。 mapReduce() 的参数是派生自 UnaryFunction 和 BinaryFunction 的匿名类;该语法简单地省略了与创建匿名实例相关的大部分冗余。
清单 13。 CICE 关闭提案下的平方和代码
Double sumOfSquares = mapReduce(myBigCollection,
UnaryFunction<Double>(Double x) return x*x; ,
BinaryFunction<Double, Double>(Double x, Double y) return x+y; );
因为表示传递给 mapReduce() 函数的对象是普通的匿名类实例,它们的主体可以引用定义在封闭范围内的变量;清单 13 和清单 7 中的方法之间的唯一区别是语法的冗长。
【讨论】:
大概你可以在 CICE 中使用菱形符号(不是像BinaryFunction
这样的接口非常好)。【参考方案2】:
Joda-time 成名的 Stephen Colebourne 最近blog a quick summary on the closures proposal。
【讨论】:
我本来打算自己发帖的,但你抢先了。 :-)以上是关于Java 中的闭包——三大提案之间的语法差异?的主要内容,如果未能解决你的问题,请参考以下文章