gpt4 book ai didi

java - 是否可以将方法引用转换为 MethodHandle?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:23:19 27 4
gpt4 key购买 nike

是否可以将方法引用(例如 SomeClass::someMethod)转换为 MethodHandle 实例?我想要编译时检查的好处(确保类和方法存在)以及使用 MethodHandle API 来检查方法的能力。

用例:我有当且仅当请求不是由特定方法触发时才需要执行的代码(以避免无休止的递归)。我想要编译时检查以确保类/方法存在,但运行时检查以将调用者与方法进行比较。

回顾一下:是否可以将方法引用转换为 MethodHandle

最佳答案

好吧,如果您能承受额外的开销和安全隐患,您可以使用Serializable 函数式接口(interface) 并解码方法引用实例的序列化形式以找到目标如 this answer 中所示或再次提出 this question and its answers .

但是,您真的应该重新考虑您的软件设计。 “避免无休止的递归”不应该通过解码某种参数对象来解决,尤其是如果你假设这个实际参数值代表你的方法的调用者。你将如何加强这种奇怪的关系?

即使是一个简单的代码更改,例如引用一个委托(delegate)给另一个方法的方法,也会破坏您的检查。这是一个简单的示例,显示了您的方法的细微问题:

public class SimpleTest {
public static void main(String... arg) {
run(SimpleTest::process);
}
static void run(BiConsumer<Object,Object> c) {
c.accept("foo", "bar");
}
static void process(Object... arg) {
Thread.dumpStack();
}
}

当运行这个程序时,它会打印如下内容:

java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1329)
at SimpleTest.process(SimpleTest.java:16)
at SimpleTest.lambda$MR$main$process$a9318f35$1(SimpleTest.java:10)
at SimpleTest$$Lambda$1/26852690.accept(Unknown Source)
at SimpleTest.run(SimpleTest.java:13)
at SimpleTest.main(SimpleTest.java:10)

显示生成的实例中的方法引用不是预期的 SimpleTest::process 而是 SimpleTest::lambda$MR$main$process$ a9318f35$1 最终将调用 process。原因是一些操作(这里是 varargs 处理)不是由生成的 interface 实例执行的,而是一个合成方法,就像你写的 run(( a,b)-> SimpleTest.process(a,b))。唯一的区别是合成方法的名称。

您不应该依赖这种脆弱的内省(introspection)来设计软件。如果你想避免递归,一个简单的 ThreadLocal 标志告诉你是否已经在你的特定方法中就可以完成这项工作。但是可能值得问问自己,为什么您的 API 首先会引发无休止的递归;似乎有一些根本性的错误……

关于java - 是否可以将方法引用转换为 MethodHandle?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26649412/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com