I have two classes A
and B
, both define method foo()
with common signature (accept nothing, return void). They don't have the common base class (or interface) that declares this method. I want to call this method on regardless As or Bs as long as they can respond to this call. This approach is called Duck Typing.
I know that there's an instruction called invokedynamic:
Each instance of an invokedynamic instruction is called a dynamic call site. A dynamic call site is originally in an unlinked state, which means that there is no method specified for the call site to invoke. As previously mentioned, a dynamic call site is linked to a method by means of a bootstrap method. A dynamic call site's bootstrap method is a method specified by the compiler for the dynamically-typed language that is called once by the JVM to link the site. The object returned from the bootstrap method permanently determines the call site's behavior.
So I tried to achive this using MethodHandles. Here's the example:
public static class A {
public void foo() {
}
}
public static class B {
public void foo() {
}
}
public static void main(String[] args) throws Throwable {
final MethodHandle foo = MethodHandles.lookup()
.findVirtual(A.class, "foo", MethodType.methodType(void.class));
foo.invoke(new B());
}
Of course, I've got:
Exception in thread "main" java.lang.ClassCastException: Cannot cast Main$B to Main$A
at sun.invoke.util.ValueConversions.newClassCastException(ValueConversions.java:461)
at sun.invoke.util.ValueConversions.castReference(ValueConversions.java:456)
at Main.main(Main.java:30)
I clearly see the difference between invokedynamic
and MethodHanle
. I see that the problem is that the foo
MethodHandle is bound to the class A
, not class B
. But is it possible for me to somehow take advantage of invokedynamic
in this particular case?
Why do I need this? This is the part of my small research project. I'm trying to understand method handles in depth and I want to call common methods on annotation instances retrieved from fields and methods. I am unable to define base class for annotations in Java, so instead of chain of instanceof's and class casts or retrieving these values using reflection violating access rights, I want to implement this duck typing if possible.
Thanks.
invokedynamic
or anything, you need an instance of the correct class to call instance methods. Of course you can't callA
methods onB
objects asA
implementation offoo()
may depend on fields / data / private function only present inA
.invokedynamic
needs an instance too. On static methods you can passnull
as thethis
parameters toinvoke
, but really: duck typing only works if you already have an instance of the object, which you are missing atm :) – Byrom