Sobrecarga com Boxing [RESOLVIDO]

13 respostas
R

Bom dia pessoal.

Lendo o livro SCJP 6 em inglês, me deparei com o seguinte exemplo na página 249:

class AddBoxing {
static void go(Integer x) { System.out.println("Integer"); }
static void go(long x) { System.out.println("long"); }
public static void main(String [] args) {
int i = 5;
go(i); // which go() will be invoked?
}
}

"… The answer is
that the compiler will choose widening over boxing, so the output will be
long "

Ou seja, o método escolhido foi o maior mais amplo que int (Long).

Testando a regra, obtive resultado diferente:

Integer foo(Integer n1) 
  System.out.println("Integer");

Long foo(Long n1)
  System.out.println("Long");

Ao chamar o método foo passando um int (primitivo) , o método Integer foi chamado. Não deveria ser o Long? Ou eu entendi errado o conceito?

Obrigado desde já

13 Respostas

Rodrigo_Sasaki

se o seu método fosse long e não Long funcionaria…

você não consegue converter um tipo primitivo int pra um wrapper Long sem um cast… portanto a VM vai escolher o único método apropriado, que é o Integer

A conversão implícita ocorre com tipos primitivos e não Wrappers.

Mikhas

É que nesse caso as opções do compilador é para fazer um Boxing com Integer ou com Long, sendo assim, ele vai escolher o boxing que cabe melhor ao tipo de dados.

R

Não digao, tentei com long e int como tipos de argumento/ retorno tb… o resultado foi o mesmo, o Integer é chamado no lugar do Long…

Acredito que não seja esse o motivo

e Mikhas, faz muito sentido o que vc disse, mas eu entendi que seria “regra” usar o mais amplo… Essa é a dúvida…

gabrielfrios

Um int cabe em um long, mas um int não tem conversão explicita para um Wrapper Long. Para fazer o teste tente Long.valueOf ou new Long() eles não recebem qualquer tipo de dado, a não seu o seu respectivo primitivo ou String.

R

Seguindo sua linha de raciocínio, como o resultado do exemplo do livro é diferente?

Now let's take our last example, and add boxing into the mix:
class AddBoxing {
static void go(Integer x) { System.out.println("Integer"); }
static void go(long x) { System.out.println("long"); }
public static void main(String [] args) {
int i = 5;
go(i); // which go() will be invoked?
}
}

As we’ve seen earlier, if the only version of the go() method was one that took
an Integer, then Java 5’s boxing capability would allow the invocation of go() to
succeed. Likewise, if only the long version existed, the compiler would use it to
handle the go() invocation. The question is, given that both methods exist, which
one will be used? In other words, does the compiler think that widening a primitive
parameter is more desirable than performing an autoboxing operation? The answer is
that the compiler will choose widening over boxing, so the output will be

long

gabrielfrios

Mas se vc usar como parametro int e long e passar um int ele vai chamar o int mesmo. Tenta o seguinte, pra vc entender. Dois metodos um recebendo um int e outro um long e passa para ele um short e vê qual ele chama.

Mikhas

Não digao, tentei com long e int como tipos de retorno tb… o resultado foi o mesmo, o Integer é chamado no lugar do Long…

Acredito que não seja esse o motivo

e Mikhas, faz muito sentido o que vc disse, mas eu entendi que seria “regra” usar o mais amplo… Essa é a dúvida…

Primeiro vamos definir:
Widening: basicamente é aumentar a precisão de um primitivo. Ex.: de int para long, de float para double, de byte para int, etc.
Boxing: É um processo que o compilador automaticamente “transforma”, ou melhor, empacota, um primitivo em seu Wrapper, sendo que esse wrappre é um objeto e não um primitivo. Ex.: int -> java.lang.Integer; long -> java.lang.Long; char -> java.lang.Character;

Tendo isso em mente, como o compilador não tem ideia do que você esta fazendo, ele faz o que é mais facil que é aumentar a precisão de um primitivo (widening) para que ele seja compativel com a assinatura do seu metodo. Se não é possivel fazer nenhum widening, ele tentar fazer o Boxing.

R

Sim, concordo com vc, com tipos primitivos ele chama o menor mais amplo que o passado, como no seu exemplo, chamaria int mesmo ( o menor mais amplo que short ).

Mas lendo o trecho do livro, entendi que seria diferente com wrappers

gabrielfrios

Entendi o seu caso, mas a regra é essa que o Mikhas colocou ai.

R

Certo, mas o livro esta errado entao ou eu entendi mal?

gabrielfrios

O livro está certo. Conseguiu entender as regras que o Mikhas colocou?

R

Sim, examinei novamente e vi que acabei confundindo o “long” com “Long”. é widening e não boxing.

Obrigado a todos pela ajuda.

gabrielfrios

Coloca um resolvido ai manolo! ^^

Criado 24 de abril de 2012
Ultima resposta 24 de abr. de 2012
Respostas 13
Participantes 4