int i = (int) novo Object (); compila muito bem embora.
Sachin Verma
Respostas:
243
Os genéricos em Java são uma construção inteiramente em tempo de compilação - o compilador transforma todos os usos genéricos em transmissões para o tipo certo. Isso é para manter a compatibilidade com versões anteriores dos tempos de execução da JVM.
Este:
List<ClassA> list =newArrayList<ClassA>();
list.add(newClassA());ClassA a = list.get(0);
é transformado em (aproximadamente):
List list =newArrayList();
list.add(newClassA());ClassA a =(ClassA)list.get(0);
Portanto, qualquer coisa usada como genérica deve ser convertida em Object (neste exemplo, get(0)retorna um Object), e os tipos primitivos não. Portanto, eles não podem ser usados em genéricos.
@DanyalAytekin - Na verdade, os genéricos Java são não tratada como modelos C ++ em tudo ...
Stephen C
20
Por que o compilador Java também não pode encaixar o tipo primitivo antes de ser usado? Isso deve ser possível, certo?
vrwim
13
@vrwim - Pode ser possível. Mas seria apenas açúcar sintático. O verdadeiro problema é que os genéricos Java com primitivas in a box são relativamente caros no tempo e no espaço em comparação com o modelo C ++ / C # ... onde o tipo primitivo real é usado.
Stephen C
6
@MauganRa sim, eu sei que posso :) Eu mantenho meu ponto de vista de que este é um projeto terrível. Espero que seja corrigido no java 10 (ou pelo menos ouvi dizer) e também em funções de ordem superior. Não me cite sobre isso.
Ced
4
@Ced concordo plenamente em que é design ruim que interminavelmente dói iniciantes ANO profissionais iguais
MauganRa
37
Em Java, os genéricos funcionam da maneira que funcionam ... pelo menos em parte ... porque foram adicionados à linguagem alguns anos após o design da linguagem 1 . Os designers de linguagem foram restringidos em suas opções de genéricos, tendo que criar um design que fosse compatível com a linguagem existente e a biblioteca de classes Java .
Outras linguagens de programação (por exemplo, C ++, C #, Ada) permitem que tipos primitivos sejam usados como tipos de parâmetro para genéricos. Mas o outro lado disso é que as implementações de genéricos (ou tipos de modelo) dessas linguagens geralmente envolvem a geração de uma cópia distinta do tipo genérico para cada parametrização de tipo.
1 - A razão pela qual os genéricos não foram incluídos no Java 1.0 foi devido à pressão do tempo. Eles achavam que tinham que liberar a linguagem Java rapidamente para preencher a nova oportunidade de mercado apresentada pelos navegadores da web. James Gosling afirmou que gostaria de incluir genéricos se eles tivessem tempo. Como seria a linguagem Java se isso tivesse acontecido, é uma incógnita.
Em java, os genéricos são implementados usando "Type apagamento" para compatibilidade com versões anteriores. Todos os tipos genéricos são convertidos em Object no tempo de execução. por exemplo,
publicclassContainer<T>{private T data;public T getData(){return data;}}
Eu acho que a pergunta aqui é "por que". Por que os genéricos exigem objetos? O consenso parece ser que é menos uma opção de design e mais ceder à compatibilidade com versões anteriores. A meu ver, se os genéricos não conseguem lidar com primitivos, isso é um déficit de funcionalidade. Tal como está, tudo o que envolve primitivas deve ser escrito para cada primitiva: em vez de Comparator <t, t>, temos Integer.compare (int a, int b), Byte.compare (byte a, byte b), etc. Isso não é uma solução!
John P
1
Sim, genéricos sobre tipos primitivos seriam um recurso obrigatório. Aqui está um link para uma proposta para ele openjdk.java.net/jeps/218
crow
5
De acordo com a Documentação Java , as variáveis de tipo genérico podem ser instanciadas apenas com tipos de referência, e não com tipos primitivos.
A atual implementação apagada de Java que produz uma classe para todas as instanciações de referência e sem suporte para instanciações primitivas. (Essa é uma tradução homogênea, e a restrição de que os genéricos de Java podem apenas atingir tipos de referência vem das limitações da tradução homogênea com relação ao conjunto de bytecodes da JVM, que usa bytecodes diferentes para operações em tipos de referência e tipos primitivos.) No entanto, os genéricos apagados em Java fornecem parametridade comportamental (métodos genéricos) e parametridade de dados (instanciações brutas e curinga de tipos genéricos).
...
foi escolhida uma estratégia de tradução homogênea, na qual variáveis genéricas do tipo são apagadas aos limites à medida que são incorporadas ao bytecode. Isso significa que, independentemente de uma classe ser genérica ou não, ela ainda é compilada em uma única classe, com o mesmo nome e cujas assinaturas de membros são iguais. A segurança do tipo é verificada em tempo de compilação e o tempo de execução é irrestrito pelo sistema de tipos genéricos. Por sua vez, isso impôs a restrição de que os genéricos só poderiam funcionar com tipos de referência, já que Object é o tipo mais geral disponível e não se estende aos tipos primitivos.
Ao criar um objeto, você não pode substituir um tipo primitivo pelo parâmetro type. Quanto ao motivo dessa restrição, é um problema de implementação do compilador. Os tipos primitivos têm suas próprias instruções de bytecode para carregar e armazenar na pilha da máquina virtual. Portanto, não é impossível compilar genéricos primitivos nesses caminhos separados de bytecode, mas isso complicaria o compilador.
Respostas:
Os genéricos em Java são uma construção inteiramente em tempo de compilação - o compilador transforma todos os usos genéricos em transmissões para o tipo certo. Isso é para manter a compatibilidade com versões anteriores dos tempos de execução da JVM.
Este:
é transformado em (aproximadamente):
Portanto, qualquer coisa usada como genérica deve ser convertida em Object (neste exemplo,
get(0)
retorna umObject
), e os tipos primitivos não. Portanto, eles não podem ser usados em genéricos.fonte
Em Java, os genéricos funcionam da maneira que funcionam ... pelo menos em parte ... porque foram adicionados à linguagem alguns anos após o design da linguagem 1 . Os designers de linguagem foram restringidos em suas opções de genéricos, tendo que criar um design que fosse compatível com a linguagem existente e a biblioteca de classes Java .
Outras linguagens de programação (por exemplo, C ++, C #, Ada) permitem que tipos primitivos sejam usados como tipos de parâmetro para genéricos. Mas o outro lado disso é que as implementações de genéricos (ou tipos de modelo) dessas linguagens geralmente envolvem a geração de uma cópia distinta do tipo genérico para cada parametrização de tipo.
1 - A razão pela qual os genéricos não foram incluídos no Java 1.0 foi devido à pressão do tempo. Eles achavam que tinham que liberar a linguagem Java rapidamente para preencher a nova oportunidade de mercado apresentada pelos navegadores da web. James Gosling afirmou que gostaria de incluir genéricos se eles tivessem tempo. Como seria a linguagem Java se isso tivesse acontecido, é uma incógnita.
fonte
Em java, os genéricos são implementados usando "Type apagamento" para compatibilidade com versões anteriores. Todos os tipos genéricos são convertidos em Object no tempo de execução. por exemplo,
será visto em tempo de execução como,
O compilador é responsável por fornecer o elenco adequado para garantir a segurança do tipo.
se tornará
Agora, a pergunta é por que "Objeto" é escolhido como tipo em tempo de execução?
Para sua informação: O Projeto Valhalla está tentando resolver o problema acima.
fonte
As coleções são definidas para exigir um tipo derivado de
java.lang.Object
. Os tipos básicos simplesmente não fazem isso.fonte
De acordo com a Documentação Java , as variáveis de tipo genérico podem ser instanciadas apenas com tipos de referência, e não com tipos primitivos.
Isso deveria acontecer no Java 10 no Projeto Valhalla .
No artigo de Brian Goetz sobre o estado da especialização
Há uma excelente explicação sobre o motivo pelo qual os genéricos não eram suportados para os primitivos. E como será implementado em versões futuras do Java.
...
fonte
Ao criar um objeto, você não pode substituir um tipo primitivo pelo parâmetro type. Quanto ao motivo dessa restrição, é um problema de implementação do compilador. Os tipos primitivos têm suas próprias instruções de bytecode para carregar e armazenar na pilha da máquina virtual. Portanto, não é impossível compilar genéricos primitivos nesses caminhos separados de bytecode, mas isso complicaria o compilador.
fonte