1 回答
TA贡献2051条经验 获得超10个赞
问题是你正在使用
factory.bindTo(ins);
Function lambda = (Function) factory.invokeExact(ins);
分别
factory.bindTo(cls.cast(instance));
return (Function) factory.invokeExact(cls.cast(instance));
调用bindTo会创建一个MethodHandle,其第一个参数绑定到指定的对象实例,但是,您忽略了新的MethodHandle. 因此,在调用未绑定句柄时,您需要再次将实例指定为参数。
对于此调用,编译时类型很重要。在第一个示例中,参数的编译时类型是正确的,因此调用具有正确的签名(TestService)Function。
在第二个示例中, 的编译时类型instance是Object,因此编译成字节码的签名将是(Object)Function,这不是完全匹配。使用cls.cast(…)无济于事,因为这将执行运行时检查并断言泛型类型匹配,如果您在这里使用类型变量,但两者都与invokeExact调用的字节码无关。
你有两个选择。您可以简单地使用invoke,它允许在调用期间进行类型转换(牺牲一点性能)
// unused factory.bindTo call omitted
return (Function) factory.invoke(instance); // noneffective cls.cast omitted
或者您更改代码以执行似乎最初打算的操作,请在调用之前绑定第一个参数:
factory = factory.bindTo(instance);
return (Function)factory.invokeExact();
因为对于预先绑定的方法句柄,不需要参数,您再次有一个精确的调用(bindTo不是签名多态的,因此,只会在运行时检查参数的类型)。
你也可以把它写成单行
return (Function)factory.bindTo(instance).invokeExact();
添加回答
举报