【问题标题】:Java - Is functional interface "lever" for lambda expressions?Java - lambda表达式的功能接口是“杠杆”吗?
【发布时间】:2015-08-14 15:00:08
【问题描述】:

我的陈述是真实吗?

这是我的代码:

public void start() {
    Consumer<Integer> someFunc = (someInt) -> {
        System.out.println("Hello lambda!");
    };
}

还有我的代码的字节码:

~启动方法

  // access flags 0x1
  public start()V
   L0
    LINENUMBER 9 L0
    INVOKEDYNAMIC accept()Ljava/util/function/Consumer; [
      // handle kind 0x6 : INVOKESTATIC
      java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
      // arguments:
      (Ljava/lang/Object;)V, 
      // handle kind 0x6 : INVOKESTATIC
      me/alexandr/SomeMainClass.lambda$start$0(Ljava/lang/Integer;)V, 
      (Ljava/lang/Integer;)V
    ]
    ASTORE 1
   L1
    LINENUMBER 12 L1
    ALOAD 1
    ICONST_1
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    INVOKEINTERFACE java/util/function/Consumer.accept (Ljava/lang/Object;)V
   L2
    LINENUMBER 13 L2
    RETURN
   L3
    LOCALVARIABLE this Lme/alexandr/SomeMainClass; L0 L3 0
    LOCALVARIABLE someFunc Ljava/util/function/Consumer; L1 L3 1
    // signature Ljava/util/function/Consumer<Ljava/lang/Integer;>;
    // declaration: java.util.function.Consumer<java.lang.Integer>
    MAXSTACK = 2
    MAXLOCALS = 2

~ 翻译后的 lambda 表达式

  // access flags 0x100A
  private static synthetic lambda$start$0(Ljava/lang/Integer;)V
   L0
    LINENUMBER 10 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "Hello lambda!"
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    LINENUMBER 11 L1
    RETURN
   L2
    LOCALVARIABLE someInt Ljava/lang/Integer; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

据我所见 - lambda 表达式 转换为 静态方法。那么,我可以说 功能接口静态方法 的“杠杆”,让我可以调用它吗?

【问题讨论】:

  • 我不明白这个问题
  • @Dici 如果我的问题难以理解,我深表歉意。英语——不是我的母语,我发现很难用它清楚地表达自己。如果有人能纠正我的问题,我会很高兴。
  • 请注意,它也可以转换为非静态方法。
  • @TagirValeev 嗯。在什么情况下?
  • @Alexandr,这是一个简短的类示例:public class L {int a;Runnable r = () -&gt; a = 5;}

标签: java lambda java-8


【解决方案1】:

如果您使用-&gt; 表示法,实现代码的实际方法将放置在`static 方法中。运行时创建的 lambda 会调用这个方法。

如果您使用:: 表示法,则不需要额外的方法,并且会在运行时生成 lambda 以调用::method

那么,我可以说功能接口是允许我调用它的静态方法的“杠杆”吗?

如果你愿意,你可以称它为“杠杆”。它可能被称为bridging 函数。正如@Dici 指出的那样,javap 使用的术语是“bootstrap method”注意:这些引导方法在元数据中存储为字符串,不会在反射或通过 ASM 的字节码中显示为 Method( JVM 内部使用的库)ASM 将它们视为元数据。

【讨论】:

  • 是的。 Bridge pattern - 正是我正在寻找的描述。谢谢。
  • 我不确定您的解释在一般情况下是否正确。请参阅此问题的答案(stackoverflow.com/questions/30514995/…)以获取反例(我认为)
  • @Dici 我假设您的意思是“引导方法”。这似乎是要使用的术语。请注意,如果您不提供 javap 所有这些选项,它不会解码引导方法,并且这些选项将作为字符串存储在类的元数据中,而不是具有自己字节码的传统方法。
  • 虽然反射没有显示对引导方法的引用,但合成方法lambda$start$0在使用Class.getDeclaredMethods()时完全可见...
  • 嗯,它实际上是三个字符串,但该声明不值得进一步讨论,因为您仍然混淆了引导方法、桥接方法和目标方法这三个完全不同的概念。问题所涉及的静态方法是目标方法,它具有附加的可执行字节码。
猜你喜欢
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-09
相关资源
最近更新 更多