Tecnicamente falando, Java possui inferências de tipo ao usar genéricos. Com um método genérico como
public <T> T foo(T t) {
return t;
}
O compilador analisará e entenderá que quando você escreve
// String
foo("bar");
// Integer
foo(new Integer(42));
Uma String será retornada para a primeira chamada e um Inteiro para a segunda chamada com base no que foi inserido como argumento. Você obterá a verificação adequada em tempo de compilação como resultado. Além disso, no Java 7, é possível obter algumas inferências de tipo adicionais ao instanciar genéricos como esse
Map<String, String> foo = new HashMap<>();
Java tem a gentileza de preencher os colchetes angulares em branco para nós. Agora, por que o Java não suporta inferências de tipo como parte da atribuição de variáveis? Em um ponto, havia uma RFE para inferir tipos nas declarações de variáveis, mas isso foi fechado como "Não será corrigido" porque
Os seres humanos se beneficiam da redundância da declaração de tipo de duas maneiras. Primeiro, o tipo redundante serve como documentação valiosa - os leitores não precisam procurar a declaração de getMap () para descobrir que tipo ela retorna. Segundo, a redundância permite ao programador declarar o tipo pretendido e, assim, se beneficiar de uma verificação cruzada realizada pelo compilador.
O colaborador que encerrou isso também observou que parece "não-java", com o qual concordo. A verbosidade do Java pode ser uma bênção e uma maldição, mas torna a linguagem o que é.
É claro que aquela RFE em particular não foi o fim dessa conversa. Durante o Java 7, esse recurso foi novamente considerado , com algumas implementações de teste sendo criadas, incluindo uma pelo próprio James Gosling. Novamente, esse recurso foi finalmente derrubado.
Com o lançamento do Java 8, agora obtivemos inferência de tipo como parte de lambdas como:
List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));
O compilador Java é capaz de examinar o método Collections#sort(List<T>, Comparator<? super T>)
e, em seguida, a interface Comparator#compare(T o1, T o2)
e determinar isso, first
e second
deve ser um String
, permitindo assim que o programador renuncie à necessidade de reafirmar o tipo na expressão lambda.