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

标签 java java-8 method-reference methodhandle

是否可以将方法引用(例如 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/

相关文章:

javascript - 使用一个方法作为另一个方法的参数 *Java Processing*

kotlin - 如何解决方法引用中的重载歧义?

java - 分析算法 最佳、最差和平均情况

java - java包在Eclipse中的位置

java - 如何在Android Studio中将onClickListener添加到ArrayAdapter

java - 如何很好地相交从两张 map 构建的两组?

Java 8 Streams : multiple filters vs. 复杂情况

java - java中的字符串replaceAll ("¾")

lambda - "Invalid lambda deserialization"当 lambda 用于接口(interface)实现时

java - 方法引用属于什么类?