对于理解 Java 8 中以下两个概念的任何帮助,将不胜感激。
我知道的
- lambda 是没有标识的对象,不应用作常规对象。
- lambda 表达式不应该从
Object
类中调用方法,如,toString
等。equals
hashCode
我想了解更多
lambda表达式必须被称为没有身份的对象有什么区别?
为什么
Object
在使用 lambda 表达式时不应该使用类中的方法?
对于理解 Java 8 中以下两个概念的任何帮助,将不胜感激。
我知道的
Object
类中调用方法,如,toString
等。equals
hashCode
我想了解更多
lambda表达式必须被称为没有身份的对象有什么区别?
为什么Object
在使用 lambda 表达式时不应该使用类中的方法?
1) lambda 是没有标识的对象,不应用作常规对象。
这不是真的。lambda 是一个 Java 对象,它确实有一个标识1。问题是故意指定生命周期以允许 Java 编译器自由优化评估它们的代码。因此,您无法知道何时会创建新的 lambda 对象,或者何时会重用现有的 lambda 对象。
JLS 15.27.4说:
“在运行时,lambda 表达式的求值类似于类实例创建表达式的求值,只要正常完成产生对对象的引用。lambda 表达式的求值不同于 lambda 主体的执行。
分配并初始化具有以下属性的类的新实例,或者引用具有以下属性的类的现有实例。……”
2) lambda 表达式不应调用
Object
类中的方法,如,toString
等。equals
hashCode
正如所写,这也是不正确的。一个 lambda 表达式可以调用这些方法。但是,当您在 lambda 对象上调用这些方法时,不建议依赖这些方法具有任何特定行为
JLS 指出:
“该类......可能会覆盖
Object
该类的方法。”
换句话说,它可能......也可能不......覆盖它们。如果您依赖这些方法的特定行为,则您的应用程序(理论上)是不可移植的。
此外,由于实例化语义也未指定, 和 的行为Object::equals
是Object::hashCode
不确定的。
最后,未指定 lambda 是否可克隆。
1 - 当然,lambda 没有名称:它是匿名的。但是名称和身份是不同的概念。
基本上,lambda 是这样做的一种便利:
@FunctionalInterface
interface A {
void b();
}
void c(A a) {
...
}
void main() {
c(new A() {
void b() {
...
}
});
}
对于不那么出色的变量名称,我深表歉意,但正如您所见,A
它是一种方法的接口。c
是一个接受A
接口的方法。A
但是,您可以在现场创建它,而不是创建自己的实现类。这就是你所说的匿名类,因为它没有名字。这是您的报价:
A lambda is an object without an identify
来自。该类没有身份。它与 lambdas 相关的原因是因为如果一个接口只有一个方法,您可以使用 lamdas 来简化它。
void main() {
c(
() -> {
...
}
);
}
这和以前完全一样。
第二部分,为什么 lambdas 不应该使用Object
's 方法,我以前不知道。您可能应该让其他人回答这个问题,但是我的猜测是 lambda 类看起来不像Object
直接扩展,因此您不能使用它的方法。