如何使用反射调用overriden方法?

时间:2016-10-27 08:05:39

标签: scala reflection

考虑我们有以下内容:

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

我尝试过以下操作(从How to call a superclass method using Java reflection获取):

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。这是真的吗?或者我只是做错了什么?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

看起来它是可能的,Java反射也适用于Scala,我只是没有阅读How to call a superclass method using Java reflection的所有答案。

以下代码有效:

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