从简单的角度来看,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);
}
}
Run Code Online (Sandbox Code Playgroud)
运行前面的例子,并检查与生成的字节码javap工具,我们可以看到,通过变量称为lambda表达式c1,c2,sup1,sup2,sup3被编译成与名称的方法:
lambda$foo$0lambda$foo$1lambda$main$2lambda$main$3lambda$main$4然而,如果我们打印出getClass()由这些变量称为每个对象(c1,c2,sup1,sup2,sup3)我们会得到,分别为:
class App$$Lambda$5/1705736037class App$$Lambda$6/455659002class App$$Lambda$1/791452441class App$$Lambda$2/531885035class App$$Lambda$3/1418481495那么,我们如何才能使运行时类名称和lambda所产生的方法名称之间的对应关系?
UPDATE
以下重复问题中指出的解决方案都没有帮助我解决我在问题中提出的问题:
我找到的唯一方法是将@Holger的解决方案从其答案(不是可接受的)调整到Java 8的问题:将lambda转换为包含clousure的Method实例.但是,在我的情况下,Method我只是在寻找方法的名称而不是对象.所以,lambdaToMethod()根据以下情况调整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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,例如lambda表达式必须强制转换Consumer<Integer>&Serializable或Supplier<String>&Serializable在@Holger描述答案.
我不知道这个解决方案是否正确,但它适用于我的示例和我正在处理的案例.
这可能会因版本而异 - 没有规范说明确切的名称- 并且这是故意这样做的;可以很好地防止代码发现与这些名称有关的聪明的事情。
| 归档时间: |
|
| 查看次数: |
2199 次 |
| 最近记录: |