问题 Java闭包类型,变量,数组和集合


Java闭包的当前规范是什么?

  1. 在提议的Java闭包规范中,我们能够 创建一个数组或闭包集合?
    如果是这样,这种语法是否可行?

    {int x, int y => boolean b}[] comparisonSwitch = {
      {int i, int j => return i>j},
      {int i, int j => return j<i},
      {int i, int j => return j==i}
    }
    
    boolean compare(int acase, int a, int b){
      return comparisonSwitch[acase].invoke(a,b);
    }
    
  2. 普通方法会被视为非匿名闭包吗?
    那么以下语法是否可行?

    public class Asdf
    {
      public boolean gt(int x, int y){
        return x>y;
      }
      public boolean lt(int x, int y){
        return x<y;
      }
      public boolean eq(int x, int y){
        return x==y;
      }
    
      {int x, int y => boolean b} GT = gt;
      {int x, int y => boolean b}[] comparisonSwitch = {
        gt, lt, eq
      }
    }
    
  3. 即封闭和方法是否可以互换?
    是否允许以下​​语法?

    // declare a method that has a closure type as an argument
    void closurator( {String s => int a} findlen ){
      // do whatever
    }
    String s = "hello";
    void useClosurator(){
      // invoke the method by supplying a non-anonymous method
      // of an object
      closurator(s.indexOf(String ss));
    }
    
  4. 我们如何能够在接口中指定闭包类型?
    我们能否做到以下几点,有效地声明方法的最终/常量引用。

    interface Closuration
    {
      public class Asdf
      {
        static public boolean gt(int x, int y){
          return x>y;
        }
        static public boolean lt(int x, int y){
          return x<y;
        }
        static public boolean eq(int x, int y){
          return x==y;
        }
      }
    
      {int x, int y => boolean b}[] comparisonSwitch = {
        Asdf.gt, Asdf.lt, Asdf.eq
      };
    }
    
  5. 由于闭包会访问代码空间,就像反射一样,使用闭包会降低程序的性能吗?如果没有,这意味着,通过借用“封闭技术”的进步来加速反思吗?

插入新问题: 实际上,闭包代码是代码空间的一部分还是变量堆的一部分,因为我预测闭包代码很容易被垃圾收集擦掉,对吧?

我可以请求您关注问题的要点,而不是示例代码中的任何语法错误/拼写错误/缺失关键字。任何错别字/错误,请为我纠正。谢谢。


11417
2018-02-07 07:42


起源

如果你们中的任何人有点过于急于将这个问题视为“不是一个真正的问题”,请阅读我的自我评论 stackoverflow.com/questions/2198734/...:这不是功课。 50岁的古代程序员需要一些诚实的帮助来做出一些战略决策。 - Blessed Geek
这是关于Neal Gafter关闭提案的问题,还是目前正在讨论的lambdas? - Tom Hawtin - tackline
当前的Project Lambda:Java语言规范草案0.1 mail.openjdk.java.net/pipermail/lambda-dev/attachments/20100122/... 正在准备0.2版。 - Tom Hawtin - tackline


答案:


你问的是JDK7的闭包工作,所以参考 javac.info 不相关。那个网站是关于现在完成的 openjdk关闭项目,它显示了如何添加 透明 Java的封闭 - 在满足Tennent的对应原则的意义上的透明度,并在粗略描述 我的博客

JKD7的工作安排在 openjdk lambda项目。规范正在快速发展,所以任何答案都是试探性的。汤姆霍廷指出, 这是最新的草案规范

在回答您的具体问题之前,值得注意的是Java具有用于变量和方法的单独命名空间。因此,在调用方法和调用函数类型的变量(在C#parlance中,委托)之间可能存在一些语法上的区别。同样,您不太可能通过命名方法来引用方法,就像引用字段一样。

回答你的问题:

  1. 这不是函数类型的建议语法。抛开那个问题,你想知道拥有一个函数类型数组是否合法。当前的规范草案表明答案是肯定的,但是已知的实现策略会导致类型系统出现漏洞,除非以某种方式不允许“函数类型数组”。规范草案小心避免讨论实施策略。可能会对VM规范进行更改以解决这些问题。如果我不得不猜测,我怀疑你问题的答案是“不”。但是,您将能够使用相同的效果 java.util.List而不是一个数组。鉴于这是分开的 项目硬币 正在考虑加入 Collection 文字和索引操作 List,它可能在语法上方便。
  2. 您想知道是否要通过命名方法来创建函数值表达式。因为(除其他原因)方法和变量出现在Java的不同命名空间中,答案可能是否定的。但是,可能会使用特定语法扩展规范,以便将方法名称视为函数值表达式。请参阅本节 方法参考 在文件中 Java的闭包(v0.6a) 对于可能考虑的一种方式,使用Stephen Colebourne提出的语法。这还没有在lambda项目的任何草案中。
  3. 见(2)的答案。
  4. 见(2)的答案。
  5. 你关心的是表现。简而言之,闭包不可能通过任何技术实现,这些技术会导致调用比方法更昂贵。出于性能原因,不需要更改VM,但出于其他原因可能是个好主意(请参阅答案1)。看到 闭包项目主页 对于指向BGGA原型的指针,这是一个更加雄心勃勃的闭包规范,它在股票jdk5 / jdk6上运行,并且可以衡量其性能。

12
2018-02-07 17:45





JDK7中的闭包目前还缺乏详细信息。在Devoxx的演示中,使用的示例非常类似于 FCM关闭提案

假设在JDK7中使用了规范,那么我认为你问题的第2,3和4部分的答案是肯定的(尽管我可能错了)。

对于第1部分 - 我认为应该可以使用数组,因为方法文字可以分配给Method对象。

对于第5部分,我怀疑性能与内部类相似。

对不起,我有点模糊 - 我希望它有点帮助。可能仍然很早就可以肯定地回答你的问题。


1
2018-02-07 10:41



语法类似于FCM(它使用哈希字符)。实际提案非常不同。 - Tom Hawtin - tackline