Chamando métodos genéricos estáticos

106

Encontrei uma situação curiosa envolvendo métodos genéricos estáticos. Este é o código:

class Foo<E>
{
    public static <E> Foo<E> createFoo()
    {
        // ...
    }
}

class Bar<E>
{
    private Foo<E> member;

    public Bar()
    {
        member = Foo.createFoo();
    }
}

Por que não preciso especificar nenhum argumento de tipo na expressão Foo.createFoo()? Isso é algum tipo de inferência de tipo? Se eu quiser ser explícito sobre isso, como posso especificar o argumento de tipo?

fredoverflow
fonte
7
Eu recomendo que você altere o parâmetro de tipo E do método createFoo. Porque o parâmetro de tipo E da classe Foo é diferente do parâmetro de tipo E do método createFoo ().
Gursel Koca
@GurselKoca Ele poderia explicitamente fazer member = Foo. <E> createFoo (); exigindo que sejam iguais ao tempo de compilação.
George Xavier de

Respostas:

183

Sim, esta é a inferência de tipo com base no destino da atribuição, conforme a seção 15.12.2.8 do JLS . Para ser explícito, você chamaria algo como:

Foo.<String>createFoo();
Jon Skeet
fonte
3
Ou, como no meu caso: Foo.<E>createFoo();Obrigado :)
fredoverflow
7
Por que isso também funciona sem a atribuição? Ou seja, a instrução Foo.createFoo(); compila muito bem ...? Isso é devido ao apagamento do tipo?
fredoverflow
9
@FredOverflow sem atribuição Eé "inferido" como sendoObject
irreputável
2
O novo local do link provavelmente seria: docs.oracle.com/javase/specs/jls/se8/html/…
Joanis
3
Uma maneira diferente de especificar o tipo de Eseria definir createFoo()pegar um argumento do tipo Class<E>(assim seria createFoo(Class<E> type)) e chamá-lo comcreateFoo(String.class)
Gavin S. Yancey