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.