Wrappers, Boxing e Atribuição

5 respostas
C

Galera,

Porque é permitido:Short s = (byte)1; E não é permitido:Long l = (int)1; // ou simplismente Long l = 1

5 Respostas

ECO2004

CodeDeveloper:
Galera,

Porque é permitido:Short s = (byte)1; E não é permitido:Long l = (int)1; // ou simplismente Long l = 1

No primeiro caso, você está passando um inteiro para bytes. Isso é possível, pois não há perda de dados.
00000001 é “1” em binário. Em inteiro, é só completar até 32 bits com 0s.

No segundo caso, há um problema de sintaxe, com ou sem a coerção.
Em Java, tipos do tipo long literais terminam com L/l. Sem isso, todo inteiro é interpretado automaticamente como inteiro.

Assim, o certo seria:

Long l = 1L;
C

ECO2004, agradeço a sua resposta.

Mas neste caso, existe um detalhe importante:Long l = (int)1; // não é permitido long l2 = (int)1; // é permitido
Com base nisso, mesmo sem o 1L, foi possível a conversão para um long (já que int cabe em long).

O que está me intrigando é o seguinte:

  • byte cabe em short
  • é permitido um primitivo byte ser atribuido a um wrapper Short (não entendo como, pois segundo a regra, não é possível ampliar ou reduzir e depois fazer o boxing)
    e então temos:

short s2 = (byte)1; // (Compila) primitivo menor pode ser atribuido a um tipo primitivo maior Short s = (byte)1; // (Compila) primitivo menor pode ser atribuido a um wrapper maior

O que está me intrigando é o seguinte:

  • int cabe em long
  • não é permitido um primitivo int ser atribuido a um wrapper Long (concordo, pois segundo a regra, não é possível ampliar ou reduzir e depois fazer o boxing)
    e então temos:

long l = (int)1; // (Compila) primitivo menor pode ser atribuido a um tipo primitivo maior, mesmo sem o L para identificar um literal long Long l2 = (int)1; // (NÃO Compila) primitivo menor NÃO pode ser atribuido a um wrapper maior

Quero entender porque a regra básica não funciona igualmente para os 2 casos.
Peço que avaliem a pergunta com atenção, pois parece uma pergunta simples de cast e boxing, mas creio que não seja.

davidbuzatto

Leia aqui, está tudo explicado, além do autor da resposta indicar o trecho da especificação da linguagem Java que trata do assunto.

ECO2004

CodeDeveloper:
ECO2004, agradeço a sua resposta.

Mas neste caso, existe um detalhe importante:Long l = (int)1; // não é permitido long l2 = (int)1; // é permitido
Com base nisso, mesmo sem o 1L, foi possível a conversão para um long (já que int cabe em long).

O que está me intrigando é o seguinte:

  • byte cabe em short
  • é permitido um primitivo byte ser atribuido a um wrapper Short (não entendo como, pois segundo a regra, não é possível ampliar ou reduzir e depois fazer o boxing)
    e então temos:

short s2 = (byte)1; // (Compila) primitivo menor pode ser atribuido a um tipo primitivo maior Short s = (byte)1; // (Compila) primitivo menor pode ser atribuido a um wrapper maior

O que está me intrigando é o seguinte:

  • int cabe em long
  • não é permitido um primitivo int ser atribuido a um wrapper Long (concordo, pois segundo a regra, não é possível ampliar ou reduzir e depois fazer o boxing)
    e então temos:

long l = (int)1; // (Compila) primitivo menor pode ser atribuido a um tipo primitivo maior, mesmo sem o L para identificar um literal long Long l2 = (int)1; // (NÃO Compila) primitivo menor NÃO pode ser atribuido a um wrapper maior

Quero entender porque a regra básica não funciona igualmente para os 2 casos.
Peço que avaliam a pergunta com atenção, pois parece uma pergunta simples de cast e boxing, mas creio que não seja.

Que nem eu disse, ocorre (ocorria) erro de sintaxe se eu não colocar um L ou l depois de um literal antes de atribui-lo à variável de tipo long.
No caso:

long l = (int)1;

Normalmente não compilaria. Aprendi que todos os valores literais inteiros eram interpretados como int. Assim, se eu quisesse um literal como long, teria que colocar L depois do valor. Será que é coisa do Java 7?

[b]A transformação de um valor de tipo menor em outro de tipo maior é chamado de upcast, usado em operações ou passagens de parâmetro. Não sabia que tinha isso com atribuições de valores a variáveis. Testei várias vezes em programas anteriores e sempre dava erro.

Por exemplo:

4/2.0 seria o mesmo que 4.0/2.0, pois ocorre um upcast.
Da mesma forma, se tenho um método void metodo(long x) e o invoco como metodo(2) ao invés de metodo(2L), ocorre também um upcast.

[/b]

No segundo caso:

Long l2 = (int)1

Volto a minha explicação anterior: colocando um L depois do literal, o valor é interpretado como um long. Envolvê-lo em um Long é trivial. Envolver um inteiro com um Long é um erro de sintaxe.

C

Obrigado pelo retorno de todos!
Deixou aqui um resumo do resumo (de acordo com o que entendi sobre o link enviado) do motivo pelo qual a situação acima acontece:

Para deixar claro:

ampliação implícita = ex:atribuir um short para um int.  int i = (short)10;

redução implícita = ex: atribuir um int para um short, mas apenas se for através de um literal explicito que seja suportado, ex: short s = 10, pois o 10 é um literal explicito que cabe em um short)

De modo geral, NÃO é permitido fazer (ampliação ou redução ) + autoboxing na mesma operação.
Exemplo: Long varLong = 10; // Não compila Neste caso, o java tem que fazer a ampliação do 10 int para 10 long, e depois fazer o boxing para a classe wrapper.

Porém é permitido long varLong = 10; // Compila Neste caso somente é feito a ampliação do 10 int para 10 long;

Porém, existe uma exceção que diz que quando os valores forem do tipo Byte, Short e Integer, é permitido realizar as 2 operações de uma vez (ampliação ou redução + boxing), como no exemplo: Short s = (byte)10; // CompilaNeste caso, o java faz a ampliação do 10 byte para 10 short, e ainda faz o boxing para a classe wrapper (10 short para new Short(10)).

Gostaria que alguém mais experiente validasse essa minha afirmação, pois como essa área de Boxing, Atribuição e Wrapper é muito complexa, pode ser que exista mais detalhes ou que eu tenha entendido algo errado.

Criado 16 de fevereiro de 2013
Ultima resposta 16 de fev. de 2013
Respostas 5
Participantes 3