当前位置:  开发笔记 > 编程语言 > 正文

Java需要关闭吗?

如何解决《Java需要关闭吗?》经验,为你挑选了8个好方法。

我最近一直在阅读关于下一版Java可能支持闭包的内容.我觉得我对封闭是什么有一个非常牢固的把握,但我想不出一个如何使面向对象语言"更好"的一个可靠的例子.任何人都可以给我一个特定的用例,需要关闭(甚至首选)?



1> Rainer Joswi..:

作为一名Lisp程序员,我希望Java社区能够理解以下不同之处:作为对象和闭包的函数.

a)功能可以命名或匿名.但它们也可以成为自己的对象.这允许函数作为参数传递,从函数返回或存储在数据结构中.这意味着函数是编程语言中的第一类对象.

匿名函数不会对语言增加太多,它们只允许您以较短的方式编写函数.

b)闭包是一个功能加上一个绑定环境.闭包可以向下传递(作为参数)或向上传递(作为返回值).这允许函数引用其环境的变量,即使周围的代码不再有效.

如果你有a)用某种语言,那么问题出现了怎么办b)?有些语言有a),但有b).在函数式编程世界中,a)(函数)和b(函数作为闭包)现在是常态.Smalltalk 很长一段时间都有a)(是匿名函数),但是Smalltalk的一些方言增加了对b)的支持(块作为闭包).

如果在语言中添加函数和闭包,可以想象你会得到一个稍微不同的编程模型.

从实用的角度来看,匿名函数添加了一些简短的表示法,您可以在其中传递或调用函数.这可能是一件好事.

闭包(函数加绑定)允许您创建一个可以访问某些变量的函数(例如,计数器值).现在,您可以将该函数存储在对象中,访问它并调用它.函数对象的上下文现在不仅是它有权访问的对象,而且还有它可以通过绑定访问的变量.这也很有用,但你可以看到变量绑定与对象变量的访问现在是一个问题:什么时候应该是一个词法变量(可以在一个闭包中访问),什么时候它应该是一个对象的变量(一个插槽).什么时候应该是一个闭包或一个对象?您可以以类似的方式使用它们.学生学习Scheme(一种Lisp方言)的常用编程练习是使用闭包编写一个简单的对象系统.

结果是更复杂的编程语言和更复杂的运行时模型.太复杂?


+1现在我理解为什么Joshua Bloch说Java已经有闭包(以匿名内部类的形式)阅读完你所说的内容后,我同意.aic的问题在于它们是冗长的方式.

2> Shog9..:

它们不会使面向对象的语言更好.它们使实用语言更加实用.

如果你用OO锤子攻击一个问题 - 把所有东西都表示为对象之间的相互作用 - 那么一个闭包没有任何意义.在基于类的OO语言中,闭包是充满烟雾的后室,其中的东西已经完成,但之后没有人谈论它.从概念上讲,这是令人憎恶的.

在实践中,它非常方便.我真的不想定义一个新类型的对象来保存上下文,为它建立"do stuff"方法,实例化它,并填充上下文...我只是想告诉编译器,"看,看看是什么我现在可以访问?这是我想要的上下文,这里是我想用它的代码 - 为我保留这个'直到我需要它".

很棒的东西.



3> jodonnell..:

最明显的事情是对所有那些只有一个名为run()或actionPerformed()或类似方法的类进行伪替换.因此,不是创建一个嵌入了Runnable的Thread,而是使用闭包.不比我们现在拥有的更强大,但更方便和简洁.

那么我们需要关闭吗?不,他们会很高兴吗?当然,只要他们不觉得狂奔,我担心他们会这样.


如果它们与JavaScript/C#/ C++ 0x闭包一样完整,它们将比匿名内部类更强大,因为它们能够捕获对局部变量的可修改引用,而不仅仅是读取的终结副本.
感谢您加强我的怀疑,即封闭只是匿名内部类的语法糖.
@Bart van Heukelom - 您确实可以,甚至更好,您可以使用为您执行此操作的语言!:)

4> Gulzar Nazim..:

我想,为了支持核心函数式编程概念,你需要闭包.通过对闭包的支持,使代码更加优雅和可组合.此外,我喜欢将代码行作为参数传递给函数.



5> jrudolph..:

有一些非常有用的"高阶函数"可以使用闭包对列表进行操作.高阶函数是具有"函数对象"作为参数的函数.

例如,将一些转换应用于列表中的每个元素是一种非常常见的操作.这种高阶函数通常称为"map"或"collect".(参见Groovy的*.spread运算符).

例如,为了在没有闭包的情况下对列表中的每个元素进行平方,您可能会写:

List squareInts(List is){
   List result = new ArrayList(is.size());
   for (Integer i:is)
      result.add(i*i);
   return result;
}

使用闭包和贴图以及建议的语法,您可以这样写:

is.map({Integer i => i*i})

(关于原始类型的装箱,这里可能存在性能问题.)

正如Pop Catalin所解释的那样,还有另一个更高阶的函数叫做'select'或'filter':它可以用来获取符合某些条件的列表中的所有元素.例如:

代替:

void onlyStringsWithMoreThan4Chars(List strings){
   List result = new ArrayList(str.size()); // should be enough
   for (String str:strings)
      if (str.length() > 4) result.add(str);
   return result;
}

相反,你可以写一些像

strings.select({String str => str.length() > 4});

使用提案.

您可以查看Groovy语法,它是Java语言的扩展,目前支持闭包.有关如何处理闭包的更多示例,请参阅" Groovy用户指南"集合一章.

一句话:

关于"封闭"一词可能需要澄清一些.我上面所说的是严格说的没有封闭.它们只是"功能对象".闭包是可以捕获 - 或"关闭" - 围绕它的代码的(词汇)上下文的一切.从这个意义上讲,Java现在有一些闭包,即匿名类:

Runnable createStringPrintingRunnable(final String str){
    return new Runnable(){
       public void run(){
          System.out.println(str); // this accesses a variable from an outer scope
       }
    };
}



6> Pop Catalin..:

Java不需要闭包,面向对象的语言可以使用中间对象来存储状态或执行操作(在Java的情况下是内部类)中执行闭包所做的一切.但是闭包是一个特征,因为它们极大地简化了代码并提高了可读性,从而提高了代码的可维护性.

我不是Java专家,但我使用的是C#3.5,闭包是我最喜欢的语言功能之一,例如以下面的语句为例:

// Example #1 with closures
public IList GetFilteredCustomerList(string filter) {
    //Here a closure is created around the filter parameter
    return Customers.Where( c => c.Name.Contains(filter)).ToList();
}

现在拿一个不使用闭包的等效示例

//Example #2 without closures, using just basic OO techniques
public IList GetFilteredCustomerList(string filter) {
    return new Customers.Where( new CustomerNameFiltrator(filter));
}
... 
public class CustomerNameFiltrator : IFilter {
    private string _filter;
    public  CustomerNameFiltrator(string filter) {
         _filter = filter;
    }
    public bool Filter(Customer customer) {
        return customer.Name.Contains( _filter);
    }
}

我知道这是C#而不是Java,但想法是一样的,闭包对简洁有用,并且使代码更短,更易读.在幕后,C#3.5的闭包看起来与示例#2非常相似,这意味着编译器在幕后创建一个私有类并将'filter'参数传递给它.

Java不需要闭包工作,作为一个你不需要它的开发人员,但是,它们是有用的并且提供好处,这意味着它们是一种生产语言所需的语言,其中一个目标就是生产力.


请注意,使用匿名类时差异要小得多

7> cygil..:

我最近一直在阅读关于下一版Java可能支持闭包的内容.我觉得我对封闭是什么有一个非常牢固的把握,但我想不出一个如何使面向对象语言"更好"的可靠例子.

好吧,大多数使用术语"闭包"的人实际上是指"函数对象",从这个意义上说,函数对象可以在某些情况下编写更简单的代码,例如在sort函数中需要自定义比较器时.

例如,在Python中:

def reversecmp(x, y):
   return y - x

a = [4, 2, 5, 9, 11]
a.sort(cmp=reversecmp)

这通过传递自定义比较functoin reversecmp以相反的顺序对列表a进行排序.lambda运算符的添加使事情变得更加紧凑:

a = [4, 2, 5, 9, 11]
a.sort(cmp=lambda x, y : y - x)

Java没有函数对象,因此它使用"函子类"来模拟它们.在Java中,您通过实现Comparator类的自定义版本并将其传递给sort函数来执行等效操作:

class ReverseComparator implements Comparator {
   public compare(Object x, Object y) {
      return (Integer) y - (Integer) x;
   }

...

List a = Arrays.asList(4, 2, 5, 9, 11);
Collections.sort(a, new ReverseComparator());

正如您所看到的,它提供与闭包相同的效果,但更笨拙,更冗长.然而,添加匿名内部类可以消除大部分痛苦:

List a = Arrays.asList(4, 2, 5, 9, 11);
Comparator reverse = new Comparator() {
   public Compare(Object x, Object y) {
       return (Integer) y - (Integer) x;
   }
}
Collections.sort(a, reverse);

所以我会说Java中的仿函数类+匿名内部类的组合足以弥补真正的函数对象的缺乏,使得它们的添加变得不必要.



8> Tom Hawtin -..:

自1.1以来,Java一直处于封闭状态,只是一种非常繁琐且有限的方式.

只要你有一些描述的回调,它们通常很有用.一个常见的情况是抽象出控制流,让有趣的代码调用一个没有外部控制流的闭包的算法.

一个简单的例子是for-each(虽然Java 1.5已经有了).虽然你可以在Java中实现一个forEach方法,但是它太冗长而无用.

现有Java已经有意义的一个例子是实现"执行"惯用法,从而抽象出资源获取和释放.例如,文件打开和关闭可以在try/finally中完成,而客户端代码不必正确地获取详细信息.

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有