Referência de método e genéricos em Java-8

11

Estou enfrentando problemas com a referência de método combinada com tipos genéricos.

Temos um código no qual precisamos chamar um método sobrecarregado, mas está falhando com erro:

Não é possível resolver o valor m1 ()

Simplifiquei meu problema para deixar claro onde está o problema.

O código a seguir falha:

public class Test {
    void test() {
        // Getting error here
        setValue(C1::m1, Integer.ONE);
    }

    <E extends I1, T> void setValue(BiConsumer<E, T> cons, T value) {
    }
}

interface I1 {
}

class C1 implements I1 {
    void m1(Integer value) {
    }

    void m1(int value) {
    }
}

Alguém pode por favor por que isso está se comportando assim?

Observe que isso não está relacionado à pergunta Referência do método Java 8 com tipos genéricos

Palhaço
fonte
não se eu remover um dos métodos ele está funcionando bem, então
Joker
Agradecimentos para reabrir esta pergunta novamente ... :)
Joker

Respostas:

7

Parece que as regras de inferência de tipo não são "inteligentes" o suficiente para resolver o conflito entre escolher a m1variante correta e gerar os parâmetros de tipo inferido corretos para a setValuechamada ( Be BigDecimalrespectivamente).

Não sei explicar por que isso falha, mas a inferência de tipos tem sido tradicionalmente uma área com regras misteriosas, bem fundamentadas e pouco intuitivas, por isso não estou muito surpreso.

Você pode solucionar esse problema adicionando uma testemunha de tipo (especificando com quais parâmetros de tipo você deseja chamar setValue); nesse momento, o compilador escolherá o m1método correto :

this.<B,BigDecimal>setValue(B::m1, BigDecimal.ONE);
Joachim Sauer
fonte
Parece que não estou alinhado com docs.oracle.com/javase/specs/jls/se8/html/…
Joker