在Java8中,以下语句“lambda是没有标识的对象”背后的背景是什么?

在Java8中,以下语句“lambda是没有标识的对象”背后的背景是什么?,java,Java,如果您能帮助理解Java8中的以下两个概念,我们将不胜感激 我所知道的 lambda是没有标识的对象,不应用作常规对象。 lambda表达式不应该从对象类(如toString、equals、hashCode等)调用方法。 我想知道更多关于 lambda表达式作为没有标识的对象调用有什么区别 为什么在使用lambda表达式时不使用Objectclass中的方法 基本上,lambda是这样做的一种便利: @FunctionalInterface interface A { void b();

如果您能帮助理解Java8中的以下两个概念,我们将不胜感激

我所知道的

lambda是没有标识的对象,不应用作常规对象。 lambda表达式不应该从对象类(如toString、equals、hashCode等)调用方法。 我想知道更多关于

lambda表达式作为没有标识的对象调用有什么区别

为什么在使用lambda表达式时不使用Objectclass中的方法


基本上,lambda是这样做的一种便利:

@FunctionalInterface
interface A {
    void b();
}

void c(A a) {
    ...
}

void main() {
    c(new A() {
        void b() {
            ...
        }
    });
}
我为不太重要的变量名道歉,但正如您所看到的,A是一个带有一个方法的接口。c是一种接受接口的方法。但是,您可以当场创建它,而不是创建自己的类来实现。这就是所谓的匿名类,因为它没有名称。这就是您的报价:

A lambda is an object without an identify
来自。该类没有标识。它与lambdas相关的原因是,如果接口只有一个方法,那么可以使用lamdas来简化它

void main() {
    c(
        () -> {
            ...
        }
    );
}
这和以前一模一样


第二部分,为什么lambdas不应该使用Object的方法,我以前不知道。您可能应该让其他人回答这个问题,但是我的猜测是lambda类看起来不像是直接扩展对象,所以您不能使用它的方法。

基本上,lambda是这样做的一种便利:

@FunctionalInterface
interface A {
    void b();
}

void c(A a) {
    ...
}

void main() {
    c(new A() {
        void b() {
            ...
        }
    });
}
我为不太重要的变量名道歉,但正如您所看到的,A是一个带有一个方法的接口。c是一种接受接口的方法。但是,您可以当场创建它,而不是创建自己的类来实现。这就是所谓的匿名类,因为它没有名称。这就是您的报价:

A lambda is an object without an identify
来自。该类没有标识。它与lambdas相关的原因是,如果接口只有一个方法,那么可以使用lamdas来简化它

void main() {
    c(
        () -> {
            ...
        }
    );
}
这和以前一模一样

第二部分,为什么lambdas不应该使用Object的方法,我以前不知道。您可能应该让其他人回答这个问题,但我的猜测是lambda类看起来不像是直接扩展对象,所以您不能使用它的方法

1 lambda是没有标识的对象,不应用作常规对象

事实并非如此。lambda是一个Java对象,它确实具有标识1。问题是故意将生命周期留待指定,以允许Java编译器自由地优化对其求值的代码。因此,您无法知道何时创建新的lambda对象,或者何时重用现有的lambda对象

JLS表示:

在运行时,lambda表达式的求值与类实例创建表达式的求值类似,只要正常完成生成对对象的引用。lambda表达式的计算不同于lambda体的执行

分配并初始化具有以下属性的类的新实例,或者引用具有以下属性的类的现有实例

2 lambda表达式不应调用对象类中的方法,如toString、equals、hashCode等

如文中所述,这也是不正确的。lambda表达式可以调用这些方法。但是,在lambda对象上调用这些方法时,不建议依赖这些方法来实现任何特定行为

联合联络小组指出:

班级。。。可以重写对象类的方法

换句话说,它可能。。。也许不是。。。超越它们。如果您依赖这些方法的特定行为,那么您的应用程序在理论上是不可移植的

此外,由于实例化语义也未指定,Object::equals和Object::hashCode的行为是不确定的

最后,还未确定lambda是否可克隆

1-当然,lambda没有名字:它是匿名的。但是名字和身份是不同的概念

1 lambda是没有标识的对象,不应用作常规对象

事实并非如此。lambda是一个Java对象,它确实具有标识1。问题是故意将生命周期留待指定,以允许Java编译器自由地优化对其求值的代码。因此,您无法知道何时创建新的lambda对象,或者何时重用现有的lambda对象

JLS表示:

在运行时,lambda表达式的求值与类实例创建表达式的求值类似,只要正常完成生成对对象的引用。lambda表达式的计算不同于lambda体的执行

具有以下属性的类的新实例都是 已配置并初始化,或者引用了具有以下属性的类的现有实例

2 lambda表达式不应调用对象类中的方法,如toString、equals、hashCode等

如文中所述,这也是不正确的。lambda表达式可以调用这些方法。但是,在lambda对象上调用这些方法时,不建议依赖这些方法来实现任何特定行为

联合联络小组指出:

班级。。。可以重写对象类的方法

换句话说,它可能。。。也许不是。。。超越它们。如果您依赖这些方法的特定行为,那么您的应用程序在理论上是不可移植的

此外,由于实例化语义也未指定,Object::equals和Object::hashCode的行为是不确定的

最后,还未确定lambda是否可克隆


1-当然,lambda没有名字:它是匿名的。但是名字和身份是不同的概念。

嘿!你能解释一下你到底不确定什么吗?这将使问题不那么依赖于某人来解释整件事,而更关注于理解问题。嘿!你能解释一下你到底不确定什么吗?这将使问题不那么依赖于某人来解释整件事,而更关注于理解问题。身份和名字是不同的概念。身份和名字是不同的概念。