有没有一种简单(惯用)的方法将 java.lang.reflect.Method 转换为 Scala 函数?
我可以通过反射检索方法,以某种方式将其与目标对象组合,并将其返回为看起来像 Scala 中的函数的东西(即您可以使用括号调用它)吗?参数列表是可变的。它不一定是“一流”函数(我已经更新了问题),只是一个看起来语法的函数调用,例如 f(args)。
到目前为止,我的尝试看起来像这样(从技术上讲,这是伪代码,只是为了避免用附加定义弄乱帖子):
class method_ref(o: AnyRef, m: java.lang.reflect.Method) { def apply(args: Any*): some_return_type = { var oa: Array[Object] = args.toArray.map { _.asInstanceOf[Object] } println("calling: " + m.toString + " with: " + oa.length) m.invoke(o, oa: _*) match { case x: some_return_type => x; case u => throw new Exception("unknown result" + u); } } }
通过上述操作,我能够克服编译器错误,但现在我遇到了运行时异常:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
示例用法类似于:
var f = ... some expression returning method_ref ...; ... var y = f(x) // looks like a function, doesn't it?
更新
将 args:Any* 更改为 args:AnyRef* 实际上解决了我的运行时问题,因此上述方法(修复)对于我想要完成的任务来说效果很好。我想我在这里遇到了一个更普遍的可变参数问题。
Can I retrieve a Method via reflection, somehow combine it with a target object, and return it as something that looks like a function in Scala (i.e. you can call it using parenthesis)? The argument list is variable. It doesn't have to be a "first-class" function (I've updated the question), just a syntactic-looking function call, e.g. f(args).
My attempt so far looks something like this (which technically is pseudo-code, just to avoid cluttering up the post with additional definitions):
class method_ref(o: AnyRef, m: java.lang.reflect.Method) { def apply(args: Any*): some_return_type = { var oa: Array[Object] = args.toArray.map { _.asInstanceOf[Object] } println("calling: " + m.toString + " with: " + oa.length) m.invoke(o, oa: _*) match { case x: some_return_type => x; case u => throw new Exception("unknown result" + u); } } }
With the above I was able to get past the compiler errors, but now I have a run-time exception:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
The example usage is something like:
var f = ... some expression returning method_ref ...; ... var y = f(x) // looks like a function, doesn't it?
UPDATE
Changing the args:Any* to args:AnyRef* actually fixed my run-time problem, so the above approach (with the fix) works fine for what I was trying to accomplish. I think I ran into a more general issue with varargs here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当然。这是我编写的一些代码,用于向函数添加接口。这并不完全是你想要的,但我认为它可以通过一些改变来适应。最困难的更改是
invoke
,您需要将调用的方法更改为通过反射获得的方法。另外,您还必须注意您正在处理的接收方法是apply
。此外,您可以使用目标对象,而不是f
。它可能看起来像这样:无论如何,这是代码:
并像这样使用它:
那里使用“manifest”有助于语法。您可以这样写:
也可以删除清单并使用 classOf 代替,并进行一些更改。
Sure. Here's some code I wrote that add an interface to a function. It's not exactly what you want, but I think it can be adapted with few changes. The most difficult change is on
invoke
, where you'll need to change the invoked method by the one obtained through reflection. Also, you'll have to take care that the received method you are processing isapply
. Also, instead off
, you'd use the target object. It should probably look something like this:Anyway, here's the code:
And use it like this:
The use of "manifest" there helps with syntax. You could write it like this:
One could also drop the manifest and use classOf instead with a few changes.
如果您不是在寻找采用方法名称的通用
invoke
,而是希望捕获特定对象上的特定方法,并且不想了解得太深进入清单等,我认为以下是一个不错的解决方案:让我们看看它的实际效果:
棘手的部分是获取返回值的正确类型。在这里,由您来提供。例如,如果您提供
classOf[CharSequence]
,它将失败,因为它不是正确的类。 (清单对此更好,但您确实要求简单......尽管我认为“简单使用”通常比“简单对功能进行编码”更好。)If you're not looking for a generic
invoke
that takes the method name--but rather, you want to capture a particular method on a particular object--and you don't want to get too deeply into manifests and such, I think the following is a decent solution:Let's see it in action:
The tricky part is getting the correct type for the return value. Here it's left up to you to supply it. For example,if you supply
classOf[CharSequence]
it will fail because it's not the right class. (Manifests are better for this, but you did ask for simple...though I think "simple to use" is generally better than "simple to code the functionality".)