O problema automático de embalagem e unboxing é um problema comum no Java. Hoje vamos dar uma olhada em alguns dos problemas de embalagem e unboxing. Este artigo fala primeiro sobre as coisas mais básicas sobre embalagem e unboxing e, em seguida, dê uma olhada nos problemas relacionados à embalagem e unboxing que são frequentemente encontrados no teste escrito abaixo.
1. O que está embalando? O que é unboxing?
No artigo anterior, o Java fornece tipos de wrapper correspondentes para cada tipo de dados básico. Quanto ao motivo pelo qual os tipos de wrapper são fornecidos para cada tipo de dados básico, ele não será explicado aqui. Amigos interessados podem consultar as informações relevantes. Antes de Java SE5, se você deseja gerar um objeto inteiro com um valor de 10, você deve fazer isso:
A cópia do código é a seguinte:
Inteiro i = novo número inteiro (10);
Desde o Java SE5, o recurso de boxe automático é fornecido. Se você deseja gerar um objeto inteiro com um valor de 10, você só precisa fazer isso:
A cópia do código é a seguinte:
Número inteiro i = 10;
Nesse processo, o objeto inteiro correspondente será criado automaticamente com base no valor numérico, que está embalando.
Então, o que é unboxing? Como o nome indica, corresponde à embalagem, que converte automaticamente o tipo de wrapper no tipo de dados básico:
A cópia do código é a seguinte:
Número inteiro i = 10; //embalagem
int n = i; // unbox
Para simplificar, a embalagem significa converter automaticamente o tipo de dados básico no tipo de wrapper; Unboxing significa converter automaticamente o tipo de wrapper para o tipo de dados básico.
A tabela a seguir é o tipo de invólucro correspondente ao tipo de dados básico:
2. Como a embalagem e a união é implementada?
Depois de entender os conceitos básicos de embalagem na seção anterior, esta seção entenderá como a embalagem e a unidade são implementadas.
Vamos tomar a classe interger como exemplo e ver um pedaço de código abaixo:
classe pública main {public static void main (string [] args) {integer i = 10; int n = i;}}Depois de descompilar o arquivo da classe, você receberá o seguinte conteúdo:
A partir do conteúdo de bytecode obtido por descompilação, pode -se observar que o método de número inteiro valorof (int) é chamado automaticamente ao embalagem. Ao Unboxing, o método Intvalue de Integer é chamado automaticamente.
Outros são semelhantes, como duplo ou caráter. Amigos que não acreditam nisso podem experimentá -lo manualmente sozinhos.
Portanto, o processo de implementação de embalagem e unboxing pode ser resumido em uma frase:
O processo de boxe é implementado chamando o método ValueOf do wrapper, enquanto o processo de unboxing é implementado chamando o método XXXValue do wrapper. (XXX representa o tipo de dados básico correspondente).
3. Perguntas relacionadas durante a entrevista
Embora a maioria das pessoas seja clara sobre os conceitos de embalagem e unboxing, eles podem não ser capazes de responder a perguntas sobre embalagem e unboxing durante entrevistas e testes escritos. Abaixo estão algumas perguntas comuns da entrevista relacionadas à embalagem/unboxing.
1. Qual é o resultado da saída do código a seguir?
classe pública main {public static void main (string [] args) {inteiro i1 = 100; número inteiro i2 = 100; inteiro i3 = 200; inteiro i4 = 200; system.out.println (i1 == i2); system.out.println (i3 == i4);}} Talvez alguns amigos digam que geram falsos, ou alguns amigos dirão que terão a produção de verdade. Mas de fato a saída é:
verdadeiro
falso
Por que esse resultado ocorre? Os resultados da saída mostram que I1 e I2 apontam para o mesmo objeto, enquanto I3 e I4 apontam para diferentes objetos. Nesse ponto, você só precisa olhar para o código -fonte para saber a verdade. O código a seguir é a implementação específica do método ValueOf do Inteiro:
Public estático Valueof (int i) {if (i> = -128 && i <= Integercache.high) Retorne Integercache.cache [i + 128]; elsereturn novo inteiro (i);} A implementação da classe Integercache é:
classe estática privada integercache {final estático int alto; cache inteiro final estático []; estático {final int baixo = -128; // valor alto pode ser configurado por propriedades h = 127; se (interno de invasão de altura // requestring //nuln {// use Long.Decode aqui para evitar os métodos que não podem ser considerados //) Long.Decode (IntegercacheHighPropValue) .IntValue (); i = Math.max (i, 127); // O tamanho máximo da matriz é inteiro.max_valueh = math.min (i, inteiro inteiro. cache.length; A partir dessas duas peças de código, ao criar um objeto inteiro através do método ValueOf, se o valor estiver entre [-128, 127], uma referência ao objeto que já existe no integgercache.cache é retornado; Caso contrário, um novo objeto inteiro é criado.
No código acima, os valores de I1 e I2 são 100, portanto os objetos existentes serão retirados diretamente do cache, portanto, I1 e I2 apontam para o mesmo objeto, enquanto I3 e I4 apontam para diferentes objetos, respectivamente.
2. Qual é o resultado da saída do código a seguir?
classe pública main {public static void main (string [] args) {duplo i1 = 100.0; duplo i2 = 100.0; duplo i3 = 200.0; duplo i4 = 200.0; system.out.println (i1 == i2); system.out.println (i3 == i4);}} Talvez alguns amigos pensem que o resultado da saída é o mesmo que a pergunta acima, mas na verdade não é. A saída real é:
falso
falso
Quanto ao motivo específico, os leitores podem verificar a implementação do valor da classe dupla.
Aqui vou explicar apenas por que o método ValueOf da classe dupla adota uma implementação diferente do método ValueOf da classe Integer. É muito simples: o número de valores inteiros em um determinado intervalo é finito, mas os números de ponto flutuante não são.
Observe que a implementação dos métodos Valueof de número inteiro, curto, byte, caráter e longo é semelhante.
A implementação do método ValueOf de dupla e flutuação é semelhante.
3. Qual é o resultado da saída do seguinte código:
classe pública main {public static void main (string [] args) {boolean i1 = false; boolean i2 = false; boolean i3 = true; boolean i4 = true; system.out.println (i1 == i2); system.out.println (i3 == i4);}} O resultado da saída é:
verdadeiro
verdadeiro
Quanto ao motivo pelo qual esse é o resultado, você também ficará claro rapidamente depois de ler o código -fonte da classe booleana. A seguir, é apresentada a implementação específica do método ValueOf de Boolean:
public static boolean valueof (booleano b) {return (b? true: false);} E o que é verdadeiro e falso? 2 Propriedades estáticas dos membros são definidas em booleanos:
public static final boolean true = new boolean (true);/** * o objeto <code> boolean </code> correspondente ao valor * primitivo * <code> false </code>. */public estático final booleano false = novo booleano (falso);
Neste ponto, todos devem entender por que a saída acima é verdadeira.
4. Fale sobre a diferença entre o número inteiro i = novo número inteiro (xxx) e o número inteiro i = xxx;
Obviamente, esse tópico pertence a um tipo relativamente amplo. Mas os pontos -chave devem ser respondidos. Deixe -me resumir as duas diferenças a seguir:
1) O primeiro método não acionará o processo automático de boxe; enquanto o segundo método será acionado;
2) A diferença na eficiência da execução e na utilização de recursos. O segundo método de eficiência da execução e uso de recursos é melhor que o primeiro em geral (observe que isso não é absoluto).
5. Qual é o resultado da saída do seguinte programa?
classe pública main {public static void main (string [] args) {inteiro a = 1; número inteiro b = 2; número inteiro c = 3; número inteiro d = 3; inteiro e = 321; número inteiro f = 321; long g = 3l; long h = 2l; System.out.println (c == d); System.out.println (e == f); System.out.println (c == (a+b)); System.out.println (c.equals) (a+b)); System.out.println (g == (a+b)); Não olhe para os resultados da saída primeiro, os leitores pensam nos resultados de saída desse código para si mesmos. O que deve ser observado aqui é que, quando os dois operandos do operador "==" são referências ao tipo de invólucro, compara se o ponteiro é o mesmo objeto e, se um dos operandos é uma expressão (ou seja, contém operações aritméticas), compara os valores numéricos (que desencadeará o processo automático de união). Além disso, para tipos de invólucro, o método igual não executa a conversão do tipo. Depois de entender esses 2 pontos, os resultados da saída acima ficarão claros de relance:
verdadeiro
falso
verdadeiro
verdadeiro
verdadeiro
falso
verdadeiro
Não há dúvida sobre o primeiro e o segundo resultado de saída. Na terceira frase, como A+B contém operações aritméticas, ela aciona o processo automático de unboxing (o método Intvalue será chamado), para comparar se os valores são iguais. Para C.Equals (A+B), o processo automático de unboxing será acionado primeiro e, em seguida, o processo de empacotamento automático será acionado. Ou seja, A+B, cada um chamará o método Intvalue e, após obter o valor após a operação de adição, o método inteiro. O mesmo vale para o seguinte, mas preste atenção aos resultados do segundo para o último e a última saída (se o valor for do tipo int, o processo de boxe chama inteiro.ValueOf; se for do tipo longo, o método de boxe chama de longa.valueof).
O exposto acima é um profundo entendimento de embalagem e unboxing em Java apresentado a você pelo editor. Espero que seja útil para você. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a você a tempo. Muito obrigado pelo seu apoio ao site wulin.com!