考虑我们有以下内容:
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提供的解决方案。