java method return type is not the actual type. For example,
public interface Foo<X extends TypeA> {
public X hello();
}
public class Bar implements Foo<TypeB> {
@Override
public TypeB hello() {
...
}
}
Method method = Bar.class.getDeclaredMethod("hello");
Class returnType = method.getReturnType();
returnType is TypeA
, not TypeB
. TypeB
is a subclass of TypeA
.
How to get the actual return type of the method? It is TypeB
, not TypeA
.
I used
Method[] methods = Bar.class.getDeclaredMethods();
and then iterate through the methods. The method returns the superclass. Verified that getDeclaredMethod("hello") do return the subclass type. Why are they different?
If you iterate through all declared methods with getDeclaredMethods()
you will find two methods of similar signature:
TypeB hello()
(this is the one you expected)TypeA hello()
(this is the one you talk of)A look into the byte code reveals following entries:
public hello()Ltest/TypeB;
//... the bytecode for your method
public synthetic bridge hello()Ltest/TypeA;
//... bytecode that delegates to hello()Ltest/TypeB
This is an effect of the javac compiler, which introduces a synthetic bridging method TypeA hello()
which only delegates to TypeB hello()
.
The reason is that only a method of same signature can be called virtually. Since the interfaces signature is TypeA hello()
any call to the interface will call TypeA hello()
in the implementation. Yet your class Bar
does not contain this method, but a replacement TypeB hello()
. To resolve this issue javac chose to bridge the method (delegate it to the replacement). I think this will save them a lot of work at runtime.
So your problem does not occur from the method returning the wrong type, but your code returning the wrong method. If you iterate the methods, call isSynthetic()
on them (true means that it is not the method of interest).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With