Eu tenho 2 interfaces, e 2 tipos de retorno.
interface interfaceA {
Publisher<String> doSomething();
}
interface interfaceB extends interfaceA {
Flow<String> doSomething();
}
interface Publisher<T>{}
class Flow<T> implements Publisher<T>{}
Assim, em tempo de execução, eu posso ver 2 métodos de interfaceB.class.getMethods()
public default my.package.Publisher my.package.interfaceB.doSomething()
public abstract my.package.Flow my.package.interfaceB.doSomething()
Em relação à primeira, é sintético. (method.getModifiers() & 0x00001000 > 0) == true
Será java gerar automaticamente estes métodos sintéticos?
Como isso funciona em geral?
O que você vê aqui é chamado um método ponte.
Para entender por que isso é necessário, temos de olhar para a forma como a JVM determina se dois métodos são diferentes:
- Cada método tem um nome. nome diferente -> método diferente.
- Cada método tem um descritor. descritor- diferente> método diferente.
O descritor contém todos os argumentos e o tipo de retorno (com os genéricos, é apagamento).
Do ponto de vista JVM Flow doSomething()
é um método diferente Publisher doSomething()
, então quando ele é convidado a fazer uma chamada invokeinterface para Publisher doSomething()
ele não vai chamar Flow doSomething()
.
Isso pode acontecer se o alvo no callsite é do tipo interfaceA
:
intefaceA foo = ...;
foo.doSomething();
Mas do ponto de vista da linguagem, ambos os métodos são os mesmos, e um substitui o outro.
Para restaurar essa relação, javac
adiciona um método ponte com o tipo de método original que só chama o método sobrecarregado.