referência é ambígua com os genéric
Estou tendo um caso bastante complicado aqui com sobrecarga de genéricos e métodos. Confira esta classe de exemplo:
public class Test {
public <T> void setValue(Parameter<T> parameter, T value) {
}
public <T> void setValue(Parameter<T> parameter, Field<T> value) {
}
public void test() {
// This works perfectly. <T> is bound to String
// ambiguity between setValue(.., String) and setValue(.., Field)
// is impossible as String and Field are incompatible
Parameter<String> p1 = getP1();
Field<String> f1 = getF1();
setValue(p1, f1);
// This causes issues. <T> is bound to Object
// ambiguity between setValue(.., Object) and setValue(.., Field)
// is possible as Object and Field are compatible
Parameter<Object> p2 = getP2();
Field<Object> f2 = getF2();
setValue(p2, f2);
}
private Parameter<String> getP1() {...}
private Parameter<Object> getP2() {...}
private Field<String> getF1() {...}
private Field<Object> getF2() {...}
}
O exemplo acima é compilado perfeitamente no Eclipse (Java 1.6), mas não com o comando Ant javac (ou com o comando javac do JDK), onde recebo esse tipo de mensagem de erro na segunda chamada desetValue
:
reference to setValue é ambíguo, tanto o método setValue (org.jooq.Parameter, T) em Test quanto o método setValue (org.jooq.Parameter, org.jooq.Field) em Test match
e acordo com a especificação e meu entendimento de como o compilador Java funciona, o método mais específico deve sempre ser escolhidhttp: //java.sun.com/docs/books/jls/third_edition/html/expressions.html#2044
De qualquer forma, mesmo que<T>
é obrigado aObject
, o que torna os doissetValue
métodos candidatos aceitáveis para invocação, aquele com oField
parâmetro @ sempre parece ser mais específico. E funciona no Eclipse, mas não no compilador do JD
ATUALIZA:
Dessa forma, funcionaria tanto no Eclipse quanto no compilador JDK (com avisos de tipos brutos, é claro). Entendo que as regras especificadas em as especificações são bastante especiais quando estão envolvidos genéricos. Mas acho isso bastante confuso:
public <T> void setValue(Parameter<T> parameter, Object value) {
}
// Here, it's easy to see that this method is more specific
public <T> void setValue(Parameter<T> parameter, Field value) {
}
UPDATE 2:
Mesmo com genéricos, posso criar esta solução alternativa em que evito o tipo<T>
sendo vinculado aObject
atsetValue
tempo de chamada, adicionando um indireto adicional e inequívoco chamadosetValue0
. Isso me faz pensar que a ligação deT
paraObject
é realmente o que está causando todos os problemas aqui:
public <T> void setValue(Parameter<T> parameter, T value) {
}
public <T> void setValue(Parameter<T> parameter, Field<T> value) {
}
public <T> void setValue0(Parameter<T> parameter, Field<T> value) {
// This call wasn't ambiguous in Java 7
// It is now ambiguous in Java 8!
setValue(parameter, value);
}
public void test() {
Parameter<Object> p2 = p2();
Field<Object> f2 = f2();
setValue0(p2, f2);
}
Estou entendendo algo errado aqui? Existe um bug do compilador conhecido relacionado a isso? Ou existe uma configuração de solução alternativa / compilador para me ajudar?
AcompanhamentoPara os interessados, enviei um relatório de bug para o Oracle e o Eclipse. A Oracle aceitou o bug, até agora, o Eclipse o analisou e o rejeitou! Parece que minha intuição está certa e isso é um bug emjavac