Observei uma diferença no comportamento de desempacotamento automático entre o Java SE 6 e o Java SE 7. Estou me perguntando por que isso acontece, porque não consigo encontrar nenhuma documentação de alterações nesse comportamento entre essas duas versões.
Aqui está um exemplo simples:
Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Isso compila bem com javac do Java SE 7. No entanto, se eu der ao compilador o argumento "-source 1.6", recebo um erro na última linha:
inconvertible types
found : java.lang.Object
required: int
Tentei baixar o Java SE 6 para compilar com o compilador nativo da versão 6 (sem qualquer opção -source). Ele concorda e dá o mesmo erro acima.
Então, o que dá? A partir de um pouco mais de experimentação, parece que o unboxing em Java 6 só pode desempacotar valores que claramente (em tempo de compilação) sejam do tipo inbox. Por exemplo, isso funciona em ambas as versões:
Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];
Portanto, parece que entre o Java 6 e 7, o recurso unboxing foi aprimorado para que pudesse lançar e desempacotar tipos de objeto de uma só vez, sem saber (em tempo de compilação) que o valor é do tipo in a box apropriado. No entanto, lendo a especificação da linguagem Java ou postagens de blog que foram escritas na época em que o Java 7 foi lançado, não consigo ver nenhuma mudança nisso, então estou me perguntando o que é a mudança e como esse "recurso" é chamado ?
Só uma curiosidade: Devido à mudança, é possível acionar unboxings "errados":
Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];
Isso compila bem, mas fornece uma ClassCastException em tempo de execução.
Alguma referência sobre isso?
Integer obj = new Integer(2); int x = (int)obj;
: funciona em Java 7, dá erro em Java 6.Respostas:
Parece que a linguagem na seção 5.5 Casting Conversion do Java 7 JLS foi atualizada em comparação com a mesma seção no Java 5/6 JLS , provavelmente para esclarecer as conversões permitidas.
Java 7 JLS diz
Java 5/6:
O Java 7 JLS também contém uma tabela (tabela 5.1) de conversões permitidas (esta tabela não está incluída no Java 5/6 JLS) de tipos de referência para primitivos. Isso lista explicitamente os casts de Object para primitivos como uma conversão de referência de estreitamento com unboxing.
O motivo é explicado neste e - mail :
fonte
Você está certo; para ser mais simples:
Isso funciona no Java 7, mas dá um erro de compilação no Java 6 e anteriores. Estranhamente, esse recurso não é documentado de maneira destacada; por exemplo, não é mencionado aqui . É discutível se é um novo recurso ou uma correção de bug (ou um novo bug?), Veja algumas informações relacionadas e discussão . O consenso parece apontar para uma ambigüidade na especificação original, o que levou a uma implementação ligeiramente incorreta / inconsistente em Java 5/6, que foi corrigida em 7, porque era crítica para a implementação de JSR 292 (Dynamically Typed Languages).
O autoboxing do Java agora tem mais algumas armadilhas e surpresas. Por exemplo
irá compilar, mas falhar (com
ClassCastException
) em tempo de execução. Isso, em vez disso, funcionará:long x = (long)(int)obj;
fonte