I have 2 interfaces, and 2 return types.
interface interfaceA {
Publisher<String> doSomething();
}
interface interfaceB extends interfaceA {
Flow<String> doSomething();
}
interface Publisher<T>{}
class Flow<T> implements Publisher<T>{}
So at runtime, I can see 2 methods of interfaceB.class.getMethods()
public default my.package.Publisher my.package.interfaceB.doSomething()
public abstract my.package.Flow my.package.interfaceB.doSomething()
Regarding the first one, it is Synthetic. (method.getModifiers() & 0x00001000 > 0) == true
Does java autogenerate this synthetic methods?
How does it work in general?
What you see here is called a bridge method.
To understand why this is needed, we have to look at how the JVM determines if two methods are different:
- Every method has a name. Different name -> different method.
- Every method has a descriptor. Different descriptor-> different method.
The descriptor contains all arguments and the return type (with generics, it's erasure).
From the JVM perspective Flow doSomething()
is a different method than Publisher doSomething()
, so when it is asked to do a invokeinterface call to Publisher doSomething()
it won't call Flow doSomething()
.
This can happen if the target at the callsite is of type interfaceA
:
intefaceA foo = ...;
foo.doSomething();
But from the language perspective, both methods are the same, and one overrides the other.
To restore this relationship, javac
adds a bridge method with the original method type that just calls the overloaded method.