在Java中,分配给函数接口的对象是什么?

在Java中,分配给函数接口的对象是什么?,java,functional-interface,Java,Functional Interface,我不熟悉Java中的Lambda表达式,所以如果这个问题看起来很愚蠢,请不要做出太苛刻的反应:如果我将其分配给功能接口,那么实现的实际对象是什么?也就是说,如果我执行List lst=new ArrayList()我将实现一个ArrayList对象。如果我执行函数fct=s->s,将创建什么对象?这个对象是不可变的吗,也就是说,当您编写lambda表达式时,让一个公共静态最终函数重用\u经常=s->String.valueOf(s) Function<String,String> f

我不熟悉Java中的Lambda表达式,所以如果这个问题看起来很愚蠢,请不要做出太苛刻的反应:如果我将其分配给
功能接口
,那么实现的实际对象是什么?也就是说,如果我执行
List lst=new ArrayList()
我将实现一个
ArrayList
对象。如果我执行
函数fct=s->s
,将创建什么对象?这个对象是不可变的吗,也就是说,当您编写lambda表达式时,让一个
公共静态最终函数重用\u经常=s->String.valueOf(s)

Function<String,String> fct = s -> s;

它是一个不可变的对象,有一个
公共静态最终函数REUSE\u经常=s->String.valueOf(s)
是有意义的,因为您可以重用同一个对象来应用不同输入的此操作。

当您编写lambda表达式时-

Function<String,String> fct = s -> s;
它是一个不可变的对象,有一个
公共静态最终函数REUSE\u经常=s->String.valueOf(s)
是有意义的,因为您可以重用同一个对象来对不同的输入应用此操作

也就是说,如果我执行List lst=new ArrayList(),我将实现一个 ArrayList对象

而是实例化一个
ArrayList

如果我执行函数,那么创建的对象是什么 fct=s->s?这个对象是不可变的吗,也就是说 具有公共静态最终函数重用\u经常=s-> 字符串。值是多少

lambda在字节码和行为/功能方面与匿名类不同。最后一个足够近,但不完全相同。

以下是两个方法,一个使用lambda,另一个使用匿名类:

public class CompareBoth {

    public void lambda() {
        Function<String,String> fct = s -> s;
        fct.apply("a");
    }


    public void anonymousClass() {
        Function<String,String> fct = new Function<String, String>() {

            @Override
            public String apply(String t) {
                return t;
            }

        };
        fct.apply("a");
    }
}
公共类比较栏{
公共无效lambda(){
功能fct=s->s;
fct.适用(“a”);
}
公共类(){
函数fct=新函数(){
@凌驾
公共字符串应用(字符串t){
返回t;
}
};
fct.适用(“a”);
}
}
这里是反汇编代码:

public class cli.CompareBoth {
  public cli.CompareBoth();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void lambda();
    Code:
       0: invokedynamic #2,  0              // InvokeDynamic #0:apply:()Ljava/util/function/Function;
       5: astore_1
       6: aload_1
       7: ldc           #3                  // String a
       9: invokeinterface #4,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      14: pop
      15: return

  public void anonymousClass();
    Code:
       0: new           #5                  // class cli/CompareBoth$1
       3: dup
       4: aload_0
       5: invokespecial #6                  // Method cli/CompareBoth$1."<init>":(Lcli/CompareBoth;)V
       8: astore_1
       9: aload_1
      10: ldc           #3                  // String a
      12: invokeinterface #4,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      17: pop
      18: return
}
public class cli.comparebot{
public cli.comparebot();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共无效lambda();
代码:
0:invokedynamic#2,0//invokedynamic#0:apply:()Ljava/util/function/function;
5:astore_1
6:aload_1
7:ldc#3//字符串a
9:invokeinterface#4,2//InterfaceMethod java/util/function/function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
14:流行音乐
15:返回
公共类();
代码:
0:new#5//class cli/comparebot$1
3:dup
4:aload_0
5:invokespecial#6//Method cli/comparebooth$1.“:(Lcli/comparebooth;)V
8:astore_1
9:aload_1
10:ldc#3//字符串a
12:invokeinterface#4,2//InterfaceMethod java/util/function/function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
17:流行音乐
18:返回
}
我们可以看到JVM对待它们的方式有所不同。

实现的实际对象是什么

创建lambda时,执行以下JVM指令:

0:invokedynamic#2,0//invokedynamic #0:apply:()Ljava/util/function/function

Java 7中引入的
InvokeDynamic
被指定为字节码指令,该指令通过动态方法调用促进动态语言(用于JVM)的实现。 你可以通过阅读了解更多信息。
现在,随着你的发展,这真的很重要吗
在大多数情况下,情况并非如此。
功能接口在功能上与匿名接口非常接近,但存在多个细微差异。
从概念上讲,我认为这样做是可以接受的。 关于函数接口不变性:

功能接口可能有状态,但设计为不可变。

因此,如果有意义,您可以重用它们。
但是,
InvokeDynamic
可以通过JVM进行优化。
因此,您不应该在代码中重复使用它们,而只是为了节省一些对象。
取而代之的是,提取常量或变量中的函数接口,因为这样可以使事情更清楚或避免重复。

也就是说,如果我执行List lst=new ArrayList(),我将实现一个 ArrayList对象

而是实例化一个
ArrayList

如果我执行函数,那么创建的对象是什么 fct=s->s?这个对象是不可变的吗,也就是说 具有公共静态最终函数重用\u经常=s-> 字符串。值是多少

lambda在字节码和行为/功能方面与匿名类不同。最后一个足够近,但不完全相同。

以下是两个方法,一个使用lambda,另一个使用匿名类:

public class CompareBoth {

    public void lambda() {
        Function<String,String> fct = s -> s;
        fct.apply("a");
    }


    public void anonymousClass() {
        Function<String,String> fct = new Function<String, String>() {

            @Override
            public String apply(String t) {
                return t;
            }

        };
        fct.apply("a");
    }
}
公共类比较栏{
公共无效lambda(){
功能fct=s->s;
fct.适用(“a”);
}
公共类(){
函数fct=新函数(){
@凌驾
公共字符串应用(字符串t){
返回t;
}
};
fct.适用(“a”);
}
}
这里是反汇编代码:

public class cli.CompareBoth {
  public cli.CompareBoth();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void lambda();
    Code:
       0: invokedynamic #2,  0              // InvokeDynamic #0:apply:()Ljava/util/function/Function;
       5: astore_1
       6: aload_1
       7: ldc           #3                  // String a
       9: invokeinterface #4,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      14: pop
      15: return

  public void anonymousClass();
    Code:
       0: new           #5                  // class cli/CompareBoth$1
       3: dup
       4: aload_0
       5: invokespecial #6                  // Method cli/CompareBoth$1."<init>":(Lcli/CompareBoth;)V
       8: astore_1
       9: aload_1
      10: ldc           #3                  // String a
      12: invokeinterface #4,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      17: pop
      18: return
}
public class cli.comparebot{
public cli.comparebot();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共无效lambda();
代码:
0:invokedynamic#2,0//invokedynamic#0:apply:()Ljava/util/function/function;
5:astore_1
6:aload_1
7:ldc#3//字符串a