Duvida basica, autoboxing mais cast [RESOLVIDO]

Galera pq o cast a seguir nao é valido? Como seria valido? Pq quando eu do um cast usando um objeto wrapper nao da erro de compilaçao por exemplo:

[code]public void go(Object numero){

	double teste =  (Double) numero;
	
	System.out.println("teste");
	System.out.println(teste);
	
}[/code]

Mas dessa forma de cima, da erro de execuçao, me gerando um ClassCastException, mas o cast nao esta correto porque alguem ai poderia me explicar? Vlw galera!

[code]
public class TesteWrapper {

static long numero = 10L; // variavel static (numero) do tipo primitivo long

public static void main(String[] args) {
	
	new TesteWrapper().go(numero); 
			
}

public void go(Object numero){ 
						
	double teste = (double) numero; // dando erro aqui.

}[/code]

e aqui erro de compilação.

alguém??

O tipo long será autoboxed para Long, que não é convertível para Double. Daí o ClassCastException.
Já no segundo caso, é pq não é possível converter um Object para um tipo primitivo.

Eu até entendo alguém que upa um tópico depois de 3 ou 4 horas, ou um dia… mas meia hora depois de ter postado?
Isso aqui é um fórum, não uma sala de chat.

nao tem como fazer conversao de jeito nenhum ali nao? uma ampliaçao por exemplo?

foi mal o “alguem”.

Você precisa converter para Long primeiro, para depois fazer a conversão nos tipos primitivos.

public class TesteWrapper {  
   static long numero = 10L; // variavel static (numero) do tipo primitivo long  
   public static void main(String[] args) {  
      new TesteWrapper().go(numero);   
   }  

   public void go(Object numero){   
      double teste = (double) (((Long)numero).longValue()); 
   }
}

Entenda o seguinte. Wrappers são um xunxo, feito únicamente para suportar números onde objetos seriam requeridos. Toda manipulação numérica mesmo deve ser feita com tipos primitivos, não com wrappers. Por isso, não existem esses casts que para tipos primitivos seriam lógicos.

O autoboxing é só um syntax suggar. Uma forma de não gastarmos tanto código para fazer uma conversão de um tipo primitivo para um wrapper.

no vlw Vini brigadao ai pela ajuda. Deixa eu so tirar minha ultima duvida aqui sobre isso

nesse caso:

double teste = (double) (((Long)numero).longValue());  // Tudo bem vc converteu o object para um wrapper Long e deu em seguida um cast (double) para um primitivo

agora nesse caso:

Double teste = (double) (((Long)numero).longValue());   // Porque o cast funciona sendo que a variavel teste e um wrapper agora?

Pq o tipo primitivo double pode ser convertido para o objeto Double via autoboxing.

Hum acho que entendi, fiz uns comentários nao sei se esta certo:

[code]package pacoteTeste;

public class TesteWrapper {

static long numero = 10L; // variavel static (numero) do tipo primitivo long

public static void main(String[] args) {
	
	new TesteWrapper().go(numero); // aqui é passado para o método go() um tipo primitivo long (número)
								  // onde a variável (número) do tipo primitivo e será representada no metodo
								 // por um object.


				
}

public void go(Object numero){ // Método que realiza um autoboxing e uma ampliação. Autoboxing e utilizado para
							  // empacotar um tipo primitivo em um objeto. Nesse caso temos um objeto (Object)
						     // onde esse objeto referencia uma variavel primitiva (long) numero. A ampliação é
							// feita com o cast realizado com a variavel primitiva (double) teste.
	
	long teste1 = ((Long)numero); // conversão de um Object referenciando um tipo primitivo long (numero) 
							     // para um objeto wrapper Long, um object nunca pode ser convertido para um tipo 
	                            // primitivo. Onde nesse caso podemos fazer um cast de Object para um objeto
							   // wrapper (Long) e atribuir á variavel teste1, pois teste1 é do mesmo tipo
					          // primitivo (long) que á variavel referenciada por Object(numero).
							    
	
	double teste = (double)((Long) numero); //conversão de um Object referenciando um tipo primitivo long (numero) 
     									   //para um objeto wrapper (Long), um object nunca pode ser convertido para 
										  //um primitivo. Nesse caso como object esta referenciando uma variavel
										 //primitiva (long) e queremos fazer uma ampliação para atribuí-la a um
										//tipo primitivo (double), somos obrigados a fazermos uma conversão de um
									   //Object para um objeto wrapper (Long) pois object esta referenciando um
									  //primitivo long e nao podemos atribuir um primitivo (long) para um objeto
									 //wrapper que nao for um (Long). Em seguida após fazer-mos um cast de um
									//object para um objeto wrapper (Long), fazemos um cast válido para (double) e
								   //atribuimos o valor a um tipo primitivo (double) teste.
	System.out.println(teste1);
	System.out.println(teste);
	
}

}
[/code]

Somente no caso de tipos primitivos, o casting faz algum tipo de conversão. Entre objetos, o casting não é conversão.
Ele apenas indica que um objeto que está sendo tratado como alguém da classe pai, pode ser tratado como alguém da classe filha. Entretanto, o objeto mesmo não sofre qualquer tipo de transformação.

O que acontece é que o autoboxing só funciona se o Java estiver entendendo o objeto em questão como um dos tipos wrappers: Double, Float, Long, Integer, Short, Byte ou Boolean. Se esse tipo estiver numa referência do tipo Object, o java não tem como garantir que a conversão pode ser feita para um tipo primitivo.

Rocomentando o seu código, portanto, fica assim.

[code]package pacoteTeste;

public class TesteWrapper {
static long numero = 10L; // variavel static (numero) do tipo primitivo long

public static void main(String[] args) {
// O método go exige um Object, mas numero é um tipo primitivo. Existe então autoboxing.
// O primitivo long é convertido para um objeto da classe Long, que é filho de Object.
new TesteWrapper().go(numero);
}

//Aqui recebemos nosso Long numa variável do tipo Object.
public void go(Object numero){

  // Informamos ao java que sabemos que o Object recebido se trata de um Long. 
  //Como se trata mesmo, não temos um ClassCastException
  //O wrapper Long só pode ser convertido para o tipo primitivo long, e a conversão ocorre nessa linha. 
  //Entretanto, até informarmos ao java que o Object se trata de um Long, o auto-unboxing não ocorrerá, 
  //por isso o cast.
  long teste1 = ((Long)numero); 
	
  //Informamos ao java que o Object se refere a um Long, para poder haver unboxing. 
  //Então, ocorre auto-unboxing desse Long para long. O tipo primitivo long já pode ser convertido para double.
  //Não há conversão de tipos direta entre wrappers (Long para Double).
  double teste = (double)((Long) numero); 
  System.out.println(teste1);
  System.out.println(teste);

}
}
[/code]

Aliás, você já se perguntou o que é uma classe Wrapper? De maneira simples, ela é isso aqui:

[code]public final class Double extends Number {
private double value;

public Double (double value) {
this.value = value;
}

public double doubleValue() {
return value;
}
} [/code]

Claro que há mais detalhes, como a implementação da interface Comparable e dos métodos equals e hashCode. Mas em essência, é isso que um wrapper significa. Simplesmente uma classe com um número primitivo dentro. A classe também não tem setters, ela é imutável. E foi criada somente para que seja possível guadar um valor primitivo onde um Object era necessário, como no caso do ArrayList:

Veja o que ocorria antes do auto-boxing:

List objetos = new ArrayList(); objetos.add(3); //Errado! 3 é tipo primitivo!

Tinhamos que fazer assim:

[code]List objetos = new ArrayList();
objetos.add(new Integer(3)); //Ok, Integer é um objeto! :slight_smile:

int valor = ((Integer)objetos.get(0)).intValue();
[/code]

Depois do auto-boxing, tanto o new Integer() quanto a chamada ao método intValue() passaram a ser otimidas. Entretanto, o java ainda as faz por debaixo dos panos. Note que a classe Double e a classe Long são ambas filhas de number. Mas Long não é filho de Double, portanto, algo assim não é permitido (pense nas regras de entre classes):

Double x = new Long(10); //Erro, Long não é filho de Double!

pô Vini brigadao de novo, meus comentarios nao estaavamm taoo errados assim não né rsrs.

Vlw mesmo!!!

Não, vc já estava no caminho. :slight_smile:

Autoboxing e Unboxing são o mesmo? Aliás Autoboxing diferencia-se de Wrapper?

Autoboxing ocorre quando o java converte automaticamente o um tipo primitivo como int, num tipo wrapper, como Integer. O Unboxing é o processo contrário.

Wrapper é a classe que guarda um tipo primitivo dentro.