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

时间:2009-11-25 18:57:20

标签: java closures java-7 inner-classes bgga

已经提出了将closures添加到Java语言的三个主要建议:

我的问题:

  • 三种提案(BGGA,CICE和FCM)在语法方面有何不同?

2 个答案:

答案 0 :(得分:7)

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 });

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

在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()方法接受锁和闭包。闭包的return type和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中的方法之间的唯一区别是语法的详细程度。

答案 1 :(得分:7)

史蒂夫·科莱伯恩(Stephen Colebourne)最近成名为乔达时代blog a quick summary on the closures proposal