Java中的闭包 - 三个主要建议之间的语法差异?

kno*_*orv 10 java closures bgga inner-classes java-7

已经提出了向Java语言添加闭包的三个主要建议:

我的问题:

  • 在语法方面,三个提案(BGGA,CICE和FCM)之间有什么区别?

JRL*_*JRL 7

这篇IBM论文给出了BGGA和CICE之间语法差异的很好的例子:

BGGA提案

BGGA提议创建了函数类型的概念,其中函数具有类型化参数列表,返回类型和throws子句.在BGGA提案中,平方和代码看起来像清单9中的代码:

清单9.使用BGGA闭包语法计算平方和

sumOfSquares = mapReduce(myBigCollection, 
                         { Double x => x * x }, 
                         { Double x, Double y => x + y });
Run Code Online (Sandbox Code Playgroud)

=>符号左侧括号内的代码标识参数的名称和类型; 右边的代码表示正在定义的匿名函数的实现.此代码可以引用块中定义的局部变量,闭包的参数,或者创建闭包的作用域中的变量.

在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

清单10中的withLock()方法接受锁和闭包.闭包的return type和throws子句是​​泛型参数; 编译器中的类型推断通常允许在不指定T和E的值的情况下调用它,如清单11和清单12所示:

清单11.调用withLock()

withLock(lock, {=>
    System.out.println("hello");
});
Run Code Online (Sandbox Code Playgroud)

清单12.使用控件构造速记调用withLock()

withLock(lock) {
    System.out.println("hello");
}
Run Code Online (Sandbox Code Playgroud)

与仿制药一样,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; });
Run Code Online (Sandbox Code Playgroud)

因为表示传递给mapReduce()的函数的对象是普通的匿名类实例,所以它们的主体可以引用封闭范围中定义的变量; 清单13和清单7中的方法之间的唯一区别是语法的详细程度.


DJ.*_*DJ. 7

joda-time成名的Stephen Colebourne最近发表了关于闭包提案的快速摘要.