Por que Java não faz inferência de tipos?

43
Sempre me perguntei por que Java não faz inferência de tipos, já que a linguagem é o que é, e sua VM é muito madura. O Go do Google é um exemplo de uma linguagem com excelente inferência de tipos e reduz a quantidade de digitação que uma pessoa precisa fazer. Existe algum motivo especial por trás desse recurso que não faz parte do Java?

    
por cobie 19.01.2013 / 00:36
fonte

5 respostas

59

Tecnicamente falando, Java tem inferência de tipos ao usar genéricos. Com um método genérico como

public <T> T foo(T t) {
  return t;
}

O compilador irá 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 Integer 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, pode-se obter inferências de tipo adicionais quando instanciar genéricos como assim

Map<String, String> foo = new HashMap<>();

Java tem a gentileza de preencher os colchetes em branco para nós. Agora, por que o Java não suporta a inferência do tipo como parte da atribuição de variáveis? Em um ponto, houve um RFE para inferência de tipo em declarações de variáveis, mas isso foi fechado "Não vai consertar" porque

Humans benefit from the redundancy of the type declaration in two ways. First, the redundant type serves as valuable documentation - readers do not have to search for the declaration of getMap() to find out what type it returns. Second, the redundancy allows the programmer to declare the intended type, and thereby benefit from a cross check performed by the compiler.

O colaborador que fechou isso também notou que ele simplesmente parece "não-java-like", com o qual eu estou de acordo. A verbosidade de Java pode ser tanto uma bênção quanto uma maldição, mas faz da linguagem o que ela é.

É claro que esse 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 criado, incluindo um pelo próprio James Gosling. Mais uma vez, esse recurso foi finalmente abatido.

Com o lançamento do Java 8, agora obtemos a inferência de tipos como parte dos lambdas:

List<String> names = Arrays.asList("Tom", "Dick", "Harry");
Collections.sort(names, (first, second) -> first.compareTo(second));

O compilador Java pode examinar o método Collections#sort(List<T>, Comparator<? super T>) e, em seguida, a interface de Comparator#compare(T o1, T o2) e determine que first e second devem ser String , permitindo que o programador tenha que reafirmar o tipo na expressão lambda.

    
por 19.01.2013 / 04:51
fonte
15

Bem, primeiro, a inferência de tipo tem nothing relacionada à maturidade do tempo de execução, seja esse tempo de execução uma CPU de 30 anos ou uma VM tão nova que os bits ainda brilhem. é tudo sobre o compilador.

Dito isso, é permitido para genéricos, a razão pela qual não é permitido para tipos não genéricos parece ser por causa da filosofia - não há nada que impeça os designers de adicioná-lo.

Atualização: parece que o java 10 oferece suporte a ele - link

    
por 19.01.2013 / 05:45
fonte
5

Até onde eu sei, quando o Java foi projetado no início dos anos 90, a inferência de tipos não era tão popular entre os idiomas mainstream (mas já era um conceito muito conhecido, por exemplo, em ML). Então, eu posso imaginar que a inferência de tipos provavelmente não fosse suportada porque o Java era destinado a programadores vindos de C ++, Pascal ou outras linguagens tradicionais que não o tinham (princípio de menor surpresa).

Além disso, um dos princípios de design do Java é escrever as coisas explicitamente para garantir que o programador e o compilador tenham o mesmo entendimento do código: a duplicação de informações reduz as chances de erros. É claro que pode ser uma questão de gosto se escrever mais alguns caracteres vale a segurança extra que ele oferece, mas essa foi a filosofia de design seguida para Java: escrever coisas explicitamente.

Eu não sei se Java terá inferência de tipos no futuro, mas IMO seria uma grande revolução para a linguagem (como Glenn Nelson mencionou, foi descrito como "não-java-like") e então também pode ser considere eliminar o nome Java em favor de um novo nome.

Se você quiser usar uma linguagem de JVM com inferência de tipos, poderá usar o Scala.

    
por 19.01.2013 / 11:54
fonte
2

Eu posso pensar em algumas razões possíveis. Uma é que a digitação explícita é auto-documentada. Java geralmente faz disso uma prioridade sobre a concisão. Outro motivo pode estar nos casos em que o tipo é um pouco ambíguo. Como quando um tipo ou qualquer subtipo pode satisfazer uma rotina. Vamos dizer que você quer usar uma lista, mas alguém vem e usa um método exclusivo para ArrayList. O JIT inferiria uma ArrayList e continuaria mesmo se você quisesse um erro de compilação.

    
por 19.01.2013 / 04:56
fonte
0

Ele contradiz a recomendação bem estabelecida de declarar variáveis usando a interface mais genérica que atenda às suas necessidades e inicializá-las com uma classe de implementação apropriada, como em

Collection<String> names = new ArrayList<>();

Efetivamente,

var names = new ArrayList<String>();

não é nada além de açúcar sintático para

ArrayList<String> names = new ArrayList<String>();

Se você quiser, seu IDE pode produzi-lo a partir da expressão new ArrayList<String>() com "um clique" (refatorar / criar variável local), mas lembre-se de que ele contradiz a recomendação "usar interfaces".

    
por 23.09.2018 / 21:27
fonte