Java8 Lambdas 与匿名类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22637900/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java8 Lambdas vs Anonymous classes
提问by Amin Abu-Taleb
Since Java8 has been recently released and its brand new lambda expressions looks to be really cool, I was wondering if this means the demise of the Anonymous classes that we were so used to.
由于 Java8 最近发布并且其全新的 lambda 表达式看起来非常酷,我想知道这是否意味着我们习惯的 Anonymous 类的消亡。
I've been researching a bit about this and found some cool examples about how Lambda expressions will systematically replace those classes, such the Collection's sort method, which used to get an Anonymous instance of Comparator to perform the sort:
我一直在对此进行一些研究,并找到了一些关于 Lambda 表达式如何系统地替换这些类的很酷的示例,例如 Collection 的 sort 方法,该方法用于获取 Comparator 的匿名实例来执行排序:
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
Now can be done using Lambdas:
现在可以使用 Lambda 来完成:
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
And looks surprisingly concise. So my question is, is there any reason to keep using those classes in Java8 instead of Lambdas?
而且看起来出奇的简洁。所以我的问题是,是否有任何理由继续在 Java8 中使用这些类而不是 Lambdas?
EDIT
编辑
Same question but in the opposite direction, what are the benefits of using Lambdas instead of Anonymous classes, since Lambdas can only be used with single method interfaces, is this new feature only a shortcut only used in few cases or is it really useful?
同样的问题,但在相反的方向,使用 Lambdas 而不是匿名类有什么好处,因为 Lambdas 只能与单一方法接口一起使用,这个新功能只是在少数情况下使用的快捷方式还是真的有用?
采纳答案by Stuart Marks
An anonymous inner class (AIC) can be used to create a subclass of an abstract class or a concrete class. An AIC can also provide a concrete implementation of an interface, including the addition of state (fields). An instance of an AIC can be referred to using this
in its method bodies, so further methods can be called on it, its state can be mutated over time, etc. None of these apply to lambdas.
匿名内部类 (AIC) 可用于创建抽象类或具体类的子类。AIC 还可以提供接口的具体实现,包括添加状态(字段)。AIC 的实例可以this
在它的方法体中引用,因此可以在其上调用更多方法,它的状态可以随时间变化等。这些都不适用于 lambda。
I'd guess that the majority of uses of AICs were to provide stateless implementations of single functions and so can be replaced with lambda expressions, but there are other uses of AICs for which lambdas cannot be used. AICs are here to stay.
我猜想 AIC 的大部分用途是提供单个函数的无状态实现,因此可以用 lambda 表达式替换,但是 AIC 的其他用途不能使用 lambda。AIC 将继续存在。
UPDATE
更新
Another difference between AICs and lambda expressions is that AICs introduce a new scope. That is, names are resolved from the AIC's superclasses and interfaces and can shadow names that occur in the lexicallyenclosing environment. For lambdas, all names are resolved lexically.
AIC 和 lambda 表达式之间的另一个区别是 AIC 引入了一个新的作用域。也就是说,名称是从 AIC 的超类和接口解析出来的,并且可以影响词法封闭环境中出现的名称。对于 lambda,所有名称都按词法解析。
回答by Rohit Jain
Lambdas though a great feature, will only work with SAM types. That is, interfaces with only a single abstract method. It would fail as soon as your interface contains more than 1 abstract method. That is where anonymous classes will be useful.
Lambdas 虽然是一个很棒的功能,但只适用于 SAM 类型。也就是说,接口只有一个抽象方法。只要您的接口包含 1 个以上的抽象方法,它就会失败。这就是匿名类将有用的地方。
So, no we cannot just ignore anonymous classes. And just FYI, your sort()
method can be more simplified, by skipping the type declaration for p1
and p2
:
所以,不,我们不能忽略匿名类。仅供参考,sort()
通过跳过p1
and的类型声明,您的方法可以更加简化p2
:
Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));
You can also use method reference here. Either you add a compareByFirstName()
method in Person
class, and use:
您也可以在此处使用方法参考。要么compareByFirstName()
在Person
类中添加一个方法,然后使用:
Collections.sort(personList, Person::compareByFirstName);
or, add a getter for firstName
, directly get the Comparator
from Comparator.comparing()
method:
或者,添加一个 getter for firstName
,直接获取Comparator
fromComparator.comparing()
方法:
Collections.sort(personList, Comparator.comparing(Person::getFirstName));
回答by Tim
Lambda's in java 8 was introduced for functional programming. Where you can avoid boilerplate code. I came across this interesting article on lambda's.
Java 8 中的 Lambda 是为函数式编程引入的。哪里可以避免样板代码。我在 lambda 上看到了这篇有趣的文章。
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
It's advisable to use lambda functions for simple logics. If implementing complex logic using lambdas will be a overhead in debugging the code in case of issue.
建议将 lambda 函数用于简单逻辑。如果使用 lambda 实现复杂的逻辑将是调试代码时出现问题的开销。
回答by Dmitriy Kuzkin
Lambda performance with Anonymous classes
匿名类的 Lambda 性能
When application is launched each class file must be loaded and verified.
当应用程序启动时,必须加载和验证每个类文件。
Anonymous classes are processed by compiler as a new subtype for the given class or interface, so there will be generated a new class file for each.
匿名类由编译器作为给定类或接口的新子类型进行处理,因此将为每个类生成一个新的类文件。
Lambdas are different at bytecode generation, they are more efficient, used invokedynamic instruction that comes with JDK7.
Lambdas 在字节码生成方面有所不同,它们更高效,使用 JDK7 自带的调用动态指令。
For Lambdas this instruction is used to delay translate lambda expression in bytecode untill runtime. (instruction will be invoked for the first time only)
对于 Lambda,此指令用于将字节码中的 lambda 表达式的转换延迟到运行时。(指令只会在第一次被调用)
As result Lambda expression will becomes a static method(created at runtime). (There is a small difference with stateles and statefull cases, they are resolved via generated method arguments)
结果 Lambda 表达式将成为静态方法(在运行时创建)。(有状态和有状态的情况有一点区别,它们是通过生成的方法参数解决的)
回答by atom217
There are following differences:
有以下区别:
1) Syntax
1) 语法
Lambda expressions looks neat as compared to Anonymous Inner Class (AIC)
与匿名内部类 (AIC) 相比,Lambda 表达式看起来很整洁
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("in run");
}
};
Thread t = new Thread(r);
t.start();
}
//syntax of lambda expression
public static void main(String[] args) {
Runnable r = ()->{System.out.println("in run");};
Thread t = new Thread(r);
t.start();
}
2)Scope
2)范围
An anonymous inner class is a class, which means that it has scope for variable defined inside the inner class.
匿名内部类是一个类,这意味着它具有内部类中定义的变量的作用域。
Whereas,lambda expression is not a scope of its own, but is part of the enclosing scope.
而lambda 表达式不是它自己的作用域,而是封闭作用域的一部分。
Similar rule applies for superand thiskeyword when using inside anonymous inner class and lambda expression. In case of anonymous inner class this keyword refers to local scope and super keyword refers to the anonymous class's super class. While in case of lambda expression this keyword refers to the object of the enclosing type and super will refer to the enclosing class's super class.
当在匿名内部类和 lambda 表达式中使用时,类似的规则适用于super和this关键字。在匿名内部类的情况下,此关键字指的是局部范围,而 super 关键字指的是匿名类的超类。而在 lambda 表达式的情况下,此关键字指代封闭类型的对象,而 super 将指代封闭类的超类。
//AIC
public static void main(String[] args) {
final int cnt = 0;
Runnable r = new Runnable() {
@Override
public void run() {
int cnt = 5;
System.out.println("in run" + cnt);
}
};
Thread t = new Thread(r);
t.start();
}
//Lambda
public static void main(String[] args) {
final int cnt = 0;
Runnable r = ()->{
int cnt = 5; //compilation error
System.out.println("in run"+cnt);};
Thread t = new Thread(r);
t.start();
}
3) Performance
3) 性能
At runtime anonymous inner classes require class loading, memory allocation and object initialization and invocation of a non-static method while lambda expression is pure compile time activity and don't incur extra cost during runtime. So performance of lambda expression is better as compare to anonymous inner classes.**
在运行时匿名内部类需要类加载、内存分配和对象初始化以及非静态方法的调用,而 lambda 表达式是纯编译时活动,不会在运行时产生额外成本。因此,与匿名内部类相比,lambda 表达式的性能更好。**
**I do realize that this point is not entirely true . Please refer following question for details. Lambda vs anonymous inner class performance: reducing the load on the ClassLoader?
**我确实意识到这一点并不完全正确。详情请参阅以下问题。 Lambda 与匿名内部类性能:减少 ClassLoader 的负载?
回答by MagGGG
- lambda syntax does not require to write the obvious code that java can infer.
- By using
invoke dynamic
, lambda are not converted back to the anonymous classesduring compile time (Java do not have to go through creating objects, just care about signature of the method, can bind to method without creating object - lambda put more emphasis on what we want to do instead what we have to do before we can do it
- lambda 语法不需要编写 java 可以推断的明显代码。
- 通过使用
invoke dynamic
,lambda在编译时不会被转换回匿名类(Java 不必经过创建对象,只关心方法的签名,可以绑定到方法而不创建对象 - lambda 更强调我们想要做什么,而不是我们在做之前必须做什么
回答by spidy
Anonymous class are there to stay because lambda is good for functions with single abstract methods but for all other cases anonymous inner classes are your saviour.
匿名类会留下来,因为 lambda 对具有单一抽象方法的函数很有用,但对于所有其他情况,匿名内部类是你的救星。