dkolmakov
dkolmakov

Reputation: 657

How to call an overriden method using reflection?

Consider we have the following:

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

I have tried to do the following (took from 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));
    }
}

but I get a runtime exception:

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

I was told that it is possible that Java reflection may not work correctly for Scala. Is it true? Or I simply do something wrong?

Upvotes: 0

Views: 102

Answers (2)

dkolmakov
dkolmakov

Reputation: 657

It looks like it is possible and Java reflection works for Scala as well, I just didn't read all answers for How to call a superclass method using Java reflection.

The following code works:

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"
    }
}

Thanks to Jesse Glick for this solution.

Upvotes: 1

Joseph Guan
Joseph Guan

Reputation: 106

Actually, you can NOT even do it in Java. Note, in the answer of "How to call a superclass method using Java reflection", it works because the Test extends the Base: public class Test extends Base {...}.

Upvotes: 1

Related Questions