匿名类中的Lambda状态和不完美

时间:2015-01-11 04:51:40

标签: java lambda java-8

我在State of Lambda上再次阅读Brian Goetz文档,其中详细说明了Java需要lambda表达式的许多原因。

在其中一段中他写道:

  

鉴于回调和其他功能风格越来越相关   习惯用法,将代码建模为Java中的数据非常重要   尽可能轻巧。在这方面,匿名内部类是   由于多种原因不完美,主要是:

     
      
  1. 庞大的语法
  2.   
  3. 围绕名称含义和this
  4. 的混淆   
  5. 不灵活的类加载和实例创建语义
  6.   
  7. 无法捕获非最终的局部变量
  8.   
  9. 无法抽象控制流程
  10.   

从这个不完美的列表中我相信我理解的项目(1),(2)和(4)。

但我不知道(3)和(5)中究竟存在什么问题。

那里的任何人都可以提供使用匿名类时这两个问题如何成为问题的例子吗?

并非所有我工作的项目都在Java 8上,因此我认为理解这些缺点非常重要,最重要的是要清楚地了解Java 8 lambdas现在的情况如何变得更好。此外,由于Brian是lambda项目的领导者之一,我认为值得花些时间考虑一下他的意思,这可能会让我产生一种顿悟: - )

2 个答案:

答案 0 :(得分:2)

5. Inability to abstract over control flow很容易。

Lambda非常适合迭代集合中的所有元素。

aCollection.forEach(myLambda)

您必须使用旧方法来循环或迭代器或类似的东西。

for( ....){
   //same code as what's in the lambda
}

这称为内部迭代。我们不仅要告诉集合,不仅要对集合中的每个元素做什么,还要如何获取每个元素。此代码按顺序迭代遍历所有对象。出于性能原因,有时候这不是最好的。

Lambdas允许我们进行外部迭代。我们只告诉集合如何处理每个元素。如何访问每个元素以及以何种顺序进行Collection实现,以最有效的方式使用内部实现知识。它甚至可能是并行的而不是顺序的。

3. Inflexible class-loading and instance-creation semantics

关于如何加载和实例化匿名类是一个较低级别的问题。我将向您指出这篇文章:http://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood

但基本上

  1. 匿名类需要为每个类创建新的类文件(MyClass $ 1等)。必须加载这个额外的类。 Lambdas不会创建新的类文件,它们的字节代码是在运行时动态创建的。
  2. Java的未来版本可能会使Lambdas的内幕不同。通过在运行时生成lambda字节码,未来的版本可以安全地改变Lambdas的创建方式而不会破坏任何内容

答案 1 :(得分:2)

我还想添加关于(3)的另一件事。 “实例创建”可能指的是当您创建匿名类(new ...)的实例时,就像创建任何类的实例一样,您可以保证获得新对象。因此,参考保证将不等!=与对任何其他对象的引用进行比较。

另一方面,对于lambdas,无法保证两次运行lambda表达式将评估为两个不同的对象。特别是,如果lambda没有捕获任何变量,那么lambda的所有实例在功能上都是相同的。在这种情况下,它可以静态地分配一个对象并在程序的持续时间内使用它。分配大量对象并不便宜,因此在可以避免创建更多对象的情况下,它会使程序更有效。