问题
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?
回答1:
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.
回答2:
The Java Language Specification specifies the following:
A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or implicitly in source code, unless the emitted construct is a class initialization method
Another definition I've seen from Java Papers is:
When an enclosing class accesses a private attribute of a nested class, Java compiler creates synthetic method for that attribute.
EDIT: It was pointed out that some of what this article states applies to an older Java version (SE7), so be mindful when reading online papers.
So for example:
import static java.lang.System.out;
public class Synthetic {
public static void main(String[] arguments) {
Synthetic.NestedClass nested = new Synthetic.NestedClass();
out.println("Age: " + nested.age);
}
private static final class NestedClass {
private String myName = "Tom";
private int age = 42;
}
}
The compiler will create synthetic methods for every private attribute being accessed. So, it'll create synthetic method (static int access$000(Synthetic$NestedClass)
) for age
, but not myName
来源:https://stackoverflow.com/questions/58065680/java-interface-synthetic-method-generation-while-narrowing-return-type