由于Java8已近日发布其全新的Lambda表达式看起来是真的很酷,我在想,如果这意味着我们已经习惯了匿名类的消亡。
我一直在研究一些关于这一点,并找到有关Lambda表达式如何将系统更换这些类,如集合的排序方法,它用于获取比较器的匿名实例进行排序一些很酷的例子:
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
现在可以使用Lambda表达式来完成:
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
而且,相貌出奇的简洁。 所以我的问题是,是否有任何理由继续使用Java8代替lambda表达式这些类?
编辑
同样的问题,但在相反的方向,有什么用,而不是匿名类Lambda表达式的好处,因为Lambda表达式只能用单一的方法接口上使用,是这一新功能仅只有在少数情况下使用的快捷方式或者是它真的有用吗?
Answer 1:
匿名内部类(AIC)可用于创建抽象类或混凝土类的子类。 一个AIC也可以提供一个具体实现的接口,包括添加状态(字段)的。 一个AIC的实例可被称为使用this
在其方法机构,因此,进一步的方法可以在其上被调用,它的状态可以随时间被突变,等等这些都不适用于lambda表达式。
我猜想,大多数工商的用途是提供单一功能的无状态实现,因此可以用lambda表达式替换,但也有不能被使用的lambda表达式工商的其他用途。 工商行政管理机关在这里停留。
UPDATE
工商行政管理机关和lambda表达式之间的另一个区别是,工商引入新的范围。 也就是说,名称由AIC的超类和接口的解决,可以阴影出现在lexcially封闭环境名。 对于lambda表达式,所有的名字是词法解决。
Answer 2:
Lambda表达式虽然一个很大的特点,将只与SAM的工作类型。 也就是说,只有一个单一的抽象方法的接口。 为你的接口包含超过1种抽象方法,将尽快失败。 这就是匿名类将是有益的。
所以,没有我们不能忽略匿名类。 而就通知你,你的sort()
方法可以更简化,通过跳过的类型声明p1
和p2
:
Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName));
你也可以在这里使用方法参考。 要么你加compareByFirstName()
的方法Person
类,并使用:
Collections.sort(personList, Person::compareByFirstName);
或者,添加用于吸气剂firstName
,直接将Comparator
从Comparator.comparing()
方法:
Collections.sort(personList, Comparator.comparing(Person::getFirstName));
Answer 3:
用匿名类LAMBDA性能
当应用程序启动每个类文件必须加载和验证。
匿名类由编译器处理为给定类或接口的新亚型,因此将产生新的类文件对每个。
Lambda表达式是在生成字节码不同,他们更高效,使用自带的JDK7 invokedynamic指令。
对于lambda表达式该指令用于延迟在字节码,直到运行时翻译lambda表达式。 (指令将只调用首次)
作为结果Lambda表达式将变成一个静态方法(在运行时创建)。 (没有与stateles和有状态的情况下,小的差异,它们通过生成方法参数解决)
Answer 4:
有以下区别:
1)语法
相较于匿名内部类Lambda表达式看起来整洁(AIC)
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)范围
匿名内部类是一类,这意味着它具有用于内部类内定义的变量范围。
然而,lambda表达式是不是它自己的范围,而封闭范围的一部分。
类似的规则适用于超 ,当匿名内部类和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)性能
在运行时,匿名内部类需要的类加载,内存分配和对象初始化和非静态方法的调用而lambda表达式是纯粹的编译时活动和运行过程中不产生额外费用。 所以lambda表达式的表现是比较匿名内部类更好。**
**我也知道这点是不完全正确的。 请参考以下详细信息的问题。 LAMBDA VS匿名内部类的性能:减少对类加载器的负荷?
Answer 5:
LAMBDA公司在Java 8中引入了函数式编程。 在这里你可以避开样板代码。 我碰到的拉姆达的这个有趣的文章。
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
它建议使用lambda函数的简单逻辑。 如果使用Lambda表达式将会在问题的情况下调试代码的开销实现复杂的逻辑。
Answer 6:
让我们在Lambda表达式和匿名类之间比较差。
1.语法
匿名类:
package com.onlyfullstack;
public class LambdaVsAnonymousClass {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Anonymous class");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
LAMBDA:
package com.onlyfullstack;
public class LambdaVsAnonymousClass {
public static void main(String[] args) {
Runnable runnable = () -> System.out.println("Lambda Expression");
Thread thread = new Thread(runnable);
thread.start();
}
}
2.执行
匿名类可以被用来实现任意数量的抽象方法的任何接口。 Lambda表达式将只与SAM(一个抽象方法)类型的工作。 也就是说仅与单个抽象方法,其也被称为功能接口的接口。 为你的接口包含超过1种抽象方法,将尽快失败。
3.编译
匿名类 :Java的创建LambdaVsAnonymousClass的java文件LambdaVsAnonymousClass.class两类文件-包含主程序LambdaVsAnonymousClass $ 1.class -包含一个匿名类
Lambda表达式 :随着Lambda表达式编译器将创建仅1如下类文件。
所以Java会为所使用的每个匿名类新的类文件。
4.性能
匿名类是由编译器处理为对于给定的类或接口新亚型所以将产生为每个使用的匿名类的新类文件。 当应用程序启动它的匿名类创建的每个类将被加载并验证。 这个过程是相当当你有大量的匿名类的耗时。
Lambda表达式相反产生直接的字节码拉姆达(如提出匿名类的语法糖的方法)的,编译声明配方(通过invokeDynamic指令)和代表真正进场施工到运行时。
因此,Lambda表达式是不是因为他们是所谓当他们被执行的匿名类更快。
欲了解更多信息,请参考以下链接:
https://onlyfullstack.blogspot.com/2019/02/lambda-vs-anonymous-class-in-java-8.html
https://onlyfullstack.blogspot.com/2019/02/how-lambda-internally-works-in-java-8.html
Answer 7:
- 拉姆达语法不需要写代码显然Java可以推断出。
- 通过
invoke dynamic
, 拉姆达不被转换回在编译时的匿名类 (Java的不必经过创建对象,只关心该方法的签名,可以绑定到方法,而无需创建对象 - 拉姆达更强调了我们想要做的,而不是我们所要做的,才可以做到这一点
Answer 8:
匿名类在那里留下来,因为拉姆达是很好的单抽象方法的功能,但对于其它情况的匿名内部类是你的救星。
文章来源: Java8 Lambdas vs Anonymous classes