首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以将方法引用转换为MethodHandle?

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

Stack Overflow用户
提问于 2014-10-30 09:34:56
回答 1查看 1.5K关注 0票数 12

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

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

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

EN

回答 1

Stack Overflow用户

发布于 2014-10-30 15:21:09

那么,如果您能够承担额外的开销和安全问题,您可以使用Serializable functional interface并对方法引用实例的序列化形式进行解码,以找到类似于this answer中演示的目标,或者使用this question and its answers再次提出。

但是,您确实应该重新考虑您的软件设计。“避免没完没了的递归”不应该通过解码某种参数对象来修正,特别是如果假设这个实际的参数值代表了方法的调用者。你怎样才能维持这种奇怪的关系?

即使是简单的代码更改,比如引用委托给其他方法的方法,也会破坏您的检查。下面是一个简单的示例,展示了您的方法存在的微妙问题:

代码语言:javascript
复制
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();
    }
}

在运行此程序时,它将打印以下内容:

代码语言:javascript
复制
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,而是最终将调用processSimpleTest::lambda$MR$main$process$a9318f35$1。原因是有些操作(这里的varargs处理)不是由生成的interface实例执行的,而是一个合成方法,就像您编写的run((a,b)-> SimpleTest.process(a,b))一样。唯一的区别是合成方法的名称。

你不应该依赖于如此脆弱的内省来设计软件。如果您想避免递归,那么使用一个简单的ThreadLocal标志来说明您是否已经在您的特定方法中就可以完成这项工作。但是,也许值得问问自己,为什么API首先会引发没完没了的递归;似乎存在一些根本错误的…。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26649412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档