如何获取lambda导致的方法名称

时间:2017-11-15 17:15:20

标签: lambda java-8

从简单的角度来看,lambda表达式被编译为static方法,因为它们不捕获this(即不访问实例成员)。

public class App {
  public static void foo(){
      Consumer<Integer> c1 = n -> {};
      Consumer<Integer> c2 = n -> {};
  }

  public static void main(String [] args) {
    Supplier<String> sup1 = () -> "I am sup1";
    Supplier<String> sup2 = () -> "I am sup2";
    Supplier<String> sup3 = () -> "I am sup3";

    Stream.of(App.class.getDeclaredMethods()).forEach(System.out::println);
  }
}

运行上一个示例并使用javap工具检查生成的字节码,我们可以看到变量引用的lambdas c1c2sup1,{{1 },sup2被编译为名称为

的方法
  • sup3
  • lambda$foo$0
  • lambda$foo$1
  • lambda$main$2
  • lambda$main$3

但是,如果我们为这些变量引用的每个对象打印lambda$main$4getClass()c1c2sup1,{{1}我们将分别获得:

  • sup2
  • sup3
  • class App$$Lambda$5/1705736037
  • class App$$Lambda$6/455659002
  • class App$$Lambda$1/791452441

那么,我们如何才能使运行时类名称和lambdas产生的方法名称之间的对应关系?

更新

以下重复问题中提到的解决方案都没有帮助我解决我在问题中提出的问题:

我找到的唯一方法是将@Holger的解决方案从其答案(不是可接受的答案)改为问题Java 8: convert lambda to a Method instance with clousure included。但是,在我的情况下,我只是在寻找方法的名称而不是class App$$Lambda$2/531885035对象。因此,将lambdaToMethod()调整为以下class App$$Lambda$3/1418481495我得到了一个解决方案:

Method

现在,必须按照@Holger answer中的描述将示例的lambdas强制转换为methodNameFromLambda()static String methodNameFromLambda(Serializable lambda) { try { Method m = lambda.getClass().getDeclaredMethod("writeReplace"); m.setAccessible(true); SerializedLambda sl=(SerializedLambda)m.invoke(lambda); return sl.getImplMethodName(); } catch(ReflectiveOperationException ex) { throw new RuntimeException(ex); } }

我不知道这个解决方案是否正确,但它适用于我的示例以及我正在处理的案例。

1 个答案:

答案 0 :(得分:3)

这可能会因版本而异 - 没有说明确切名称的说明 - 并且故意;以防止可能找到与这些名称有关的聪明事情的代码。