Isso está realmente ampliando vs autoboxing?

votos
27

Eu vi isso em uma resposta a outra pergunta , em referência a deficiências da especificação Java:

Há mais deficiências e este é um tema sutil. Verifique este para fora:

public class methodOverloading{
     public static void hello(Integer x){
          System.out.println(Integer);
     }

     public static void hello(long x){
          System.out.println(long);
     }

     public static void main(String[] args){
         int i = 5;
         hello(i);
     }
}

Aqui longo seria impresso (não verifiquei por mim mesmo), porque o compilador escolhe alargamento sobre auto-boxing. Tenha cuidado ao usar auto-boxing ou não usá-lo em tudo!

Temos certeza de que este é realmente um exemplo de ampliação em vez de autoboxing, ou é algo totalmente diferente?

No meu varredura inicial, eu concordo com a afirmação de que a saída seria longo com base no ique está sendo declarado como um primitivo e não um objeto. No entanto, se você mudou

hello(long x)

para

hello(Long x)

a saída seria imprimir Integer

O que realmente está acontecendo aqui? Não sei nada sobre os compiladores / intérpretes de bytecode para java ...

Publicado 07/08/2008 em 17:30
fonte usuário
Em outras línguas...                            


3 respostas

votos
13

No primeiro caso, você tem a acontecer uma conversão aumentando. Isto pode ser visto quando runinng o programa utilitário "javap" (incluído w / o JDK), na classe compilado:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   i2l
   4:   invokestatic    #6; //Method hello:(J)V
   7:   return

}

Claramente, você vê o I2L, que é o mnemônico para a ampliação instrução bytecode Integer-To-Long. Ver referência aqui .

E no outro caso, substituindo o "long x" com o objeto "Long x" assinatura, você terá este código no método principal:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   invokestatic    #7; //Method hello:(Ljava/lang/Integer;)V
   9:   return

}

Então você vê o compilador criou a instrução Integer.valueOf (int), para a caixa de primitivo no interior do invólucro.

Respondeu 07/08/2008 em 19:18
fonte usuário

votos
4

Sim, é, experimentá-lo em um teste. Você vai ver "long" impresso. Ele está se ampliando porque Java vão optar por alargar o int em um tempo antes que ele escolhe para Autobox-lo para um inteiro, então o método Olá (longo) é escolhido para ser chamado.

Edit: o post original que está sendo referenciado .

Além disso Edit: A razão a segunda opção seria imprimir Integer é porque não existe um "alargamento" em um primitivo maior como uma opção, por isso deve caixa-lo, assim Integer é a única opção. Além disso, java só vai autobox ao tipo original, para que ele daria um erro do compilador se você deixar o Olá (Long) e Olá removido (Integer).

Respondeu 07/08/2008 em 17:36
fonte usuário

votos
2

Outra coisa interessante com este exemplo é a sobrecarga de método. A combinação do tipo de ampliação e sobrecarga de método trabalhando apenas porque o compilador tem que tomar uma decisão de qual método de escolha. Considere o seguinte exemplo:

public static void hello(Collection x){
   System.out.println("Collection");
}

public static void hello(List x){
   System.out.println("List");
}

public static void main(String[] args){
   Collection col = new ArrayList();
   hello(col);
}

Ele não usa o tipo de tempo de execução que é List, ele usa o tipo de tempo de compilação que é coleção e, portanto, imprime "Coleção".

I incentivar o seu ler Effective Java , que abriu meus olhos para alguns casos canto do JLS.

Respondeu 07/08/2008 em 20:02
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more