如何使用反射调用重写的方法



考虑我们有以下内容:

 class Base { def name = "Base" }
 class Successor extends Base {
    override def name = "Successor"
 }

我尝试做以下事情(取自如何使用Java反射调用超类方法):

import java.lang.invoke.{MethodHandles, MethodHandle, MethodType}
object TestApp {
    def main(args: Array[String]) {
        val a = new Successor;
        val h1 = MethodHandles.lookup().findSpecial(classOf[Base],
                                                    "name",
                                                    MethodType.methodType(classOf[String]),
                                                    classOf[Successor]);
        println(h1.invoke(a));
    }
}

但是我得到一个运行时异常:

java.lang.IllegalAccessException: no private access for invokespecial: class Successor, from TestApp$

我被告知Java反射可能不能正确地工作于Scala。这是真的吗?或者我只是做错了什么?

实际上,你甚至不能在Java中做到这一点。注意,在"如何使用Java反射调用超类方法"的回答中,它的工作是因为Test扩展了Base: public class Test extends Base {...}

看起来这是可能的,Java反射也适用于Scala,我只是没有阅读如何使用Java反射调用超类方法的所有答案。

下面的代码可以工作:

object TestApp {
    def main(args: Array[String]) {
        val a = new Successor;
        val impl_lookup = classOf[MethodHandles.Lookup].getDeclaredField("IMPL_LOOKUP")
        impl_lookup.setAccessible(true)
        val lkp = impl_lookup.get(null).asInstanceOf[MethodHandles.Lookup];
        val h1 = lkp.findSpecial(classOf[Base],
                                "name",
                                MethodType.methodType(classOf[String]),
                                classOf[Successor])
        println(h1.invoke(a)) // prints "Base"
        println(a.name)       // prints "Successor"
    }
}

感谢Jesse Glick提供的解决方案。

相关内容

  • 没有找到相关文章

最新更新