Esta secção continua a investigar a embalagem, apresenta a classe Integer, sob Classes de caracteres seção, longo e Integer semelhante, ele não é mais uma apresentação separada, outras classes básicas foram introduzidos ao longo, não repeti-los.
O que um simples inteiro para apresentá-lo? Tem algumas operações binárias, olhamos para, além disso, nós também analisar a sua valueOf alcançado.
Por que devemos nos preocupar com o código que implementa-lo? Na maioria dos casos, não se importa, vamos ser capazes de usá-lo, nós, principalmente para aprender, especialmente onde a operação binária, é a base do computador binário, mas o código é muitas vezes obscuro, nós queremos que eles têm um mais para limpar uma compreensão profunda.
Vamos olhar pouco flip.
aleta bit
uso
Integer tem dois métodos estáticos que podem ser capotou pouco:
int public static reversa (int i) reverseBytes int public static (int i)
Bit aleta é um int como binário, bit por bit para a direita da esquerda permutáveis, inverso é pouco permutáveis, reverseBytes é intercambiável por byte. Vamos olhar um exemplo:
int a = 0x12345678; System.out.printlnl (Integer.toBinaryString (a)); int r = Integer.reverse (a); System.out.printlnl (Integer.toBinaryString (r)); int RB = Integer.reverseBytes (a); System.out.printlnl (Integer.toHexString (Rb));
a é um número inteiro, hexadecimal atribuído, a série binária que é emitido em primeiro lugar, em seguida, o reverso produz um binário, reverseBytes hexadecimais saída final, como saída:
10010001101000101011001111000 11110011010100010110001001000 78563412
reverseBytes é invertido byte, uma representação hexadecimal de 78 bytes, é 12, então o resultado é 78563412 fácil de entender.
aleta binário à primeira vista é errado, porque a saída não é 32, 0:00 saída anterior ignorado, enchemos 32 Look:
00010010001101000101011001111000 00011110011010100010110001001000
Os resultados à direita.
Estes dois métodos são como consegui-lo?
reverseBytes
Olhe código reverseBytes:
reverseBytes int public static (int i) { return ((i >>> 24)) | ((i >> 8) & 0xFF00) | ((i << 8) & 0xFF0000) | ((i << 24)); }
Parâmetro i é igual a 0x12345678, por exemplo, analisamos o processo de implementação:
i >>> 24 deslocamento para a direita sem sinal, o byte mais elevado moveu-se para o bit mais baixo, o resultado é 0x00000012.
(I >> 8) & 0xFF00, movido para a esquerda do segundo byte para a direita da segunda, i >> 8 resultado 0x00123456, em seguida, & 0xFF00, está reservada para a direita do segundo byte, o resultado é 0x00003400.
(I << 8) & 0xFF0000, mudou-se para o lado direito do segundo byte do segundo esquerda, i << 8 resultado 0x34567800, em seguida, & 0xFF0000, está reservada para o direito do terceiro byte, o resultado é 0x00560000.
i << 24, o resultado é 0x78000000, o mais à esquerda e mais à direita bytes movido.
Os quatro resultados, em seguida, ou operações |, o resultado é 0x78563412, por isso, esquerda, direita e e ou operações, para atingir o objectivo de bytes invertida.
marcha ré
Nós olhamos para o código inverso:
int public static reversa (int i) { // HD, Figura 7-1 i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555; i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333; i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f; i = (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24); voltar i; }
Embora esse código é muito curto, mas muito obscuro, no final o que isso significa?
A primeira linha é um comentário, "HD, Figura 7-1", O que significa? HD é representado por um livro chamado Hacker Delight, HD sua sigla, Figura 7-1 é um diagrama para 7-1 livro, o livro, o conteúdo como mostrado abaixo:
Como pode ser visto, de número inteiro em código inversa é uma cópia do livro de código na figura 1/7, o código interpretado na figura também mostra, que traduzi-lo.
A ideia básica da aleta aplicação pouco eficiente, pouco permuta única adjacente em primeiro lugar, e, em seguida, como um grupo de dois, em seguida, a troca de bits adjacentes, seguidos por um grupo de quatro comutação, em seguida, oito, dezasseis, dezasseis após o bit é completa. Esta ideia aplica-se não só para binário, decimal, também é aplicável, para facilitar a compreensão, olhamos para exemplos decimais, tais como digital flip 12345678,
A primeira rodada, a única trocados digitais adjacentes, o resultado é:
21 43 65 87
Segunda rodada, um conjunto de dois números para a troca de lado, o resultado é:
43 21 87 65
A terceira ronda, um grupo de quatro números para a troca de lado, o resultado é:
8765 4321
Virar concluída.
Para decimal, a eficiência não é alta, mas para binário, o produto é eficiente porque uma pluralidade de bits binários adjacentes pode ser trocado em uma instrução.
Esta linha é adjacente a um único intercâmbio:
x = (x & 0x55555555) << 1 | (X & 0xAAAAAAAA) >>> 1;
5 é 0101,0x55555555 representação binária binário é:
01010101010101010101010101010101
x & 0x55555555 é levar o bit ímpar de x.
Um binário é 1010,0xAAAAAAAA representação binária é:
10101010101010101010101010101010
x & 0xAAAAAAAA é tomada pouco x mesmo.
(X & 0x55555555) << 1 | (X & 0xAAAAAAAA) >>> 1;
X é representado pelo pouco estranho aos pedaços, até mesmo para a esquerda para a direita, então | fusão, atingir o objectivo de bits adjacentes intercambiáveis. Este código pode ser optimizado para ter um pequeno, apenas uma constante 0x55555555, e, em seguida, a segunda metade da primeira operação de deslocamento, torna-se:
(I & 0x55555555) << 1 | (I >>> 1) & 0x55555555;
Da mesma forma, o código seguinte é de dois bits num grupo de bits adjacentes são intercambiáveis:
i = (i & 0x33333333) << 2 | (I & 0xCCCCCCCC) >>> 2;
3 é 0011,0x33333333 representação binária binário é:
00110011001100110011001100110011
x x & 0x33333333 é tomar dois da metade inferior de um conjunto.
C é a representação binária 1100,0xCCCCCCCC binário é:
11001100110011001100110011001100
x x & 0xCCCCCCCC é participar em dois meia altura em um conjunto.
(I & 0x33333333) << 2 | (I & 0xCCCCCCCC) >>> 2;
X é representado por um conjunto de dois, a metade inferior à metade inferior do elevado deslocamento deslocada, alta, então | combinadas, alcançar o propósito de troca. Da mesma forma, a constante pode ser removido 0xCCCCCCCC, o código pode ser optimizado para:
(I & 0x33333333) << 2 | (I >>> 2) & 0x33333333;
Da mesma forma, o código seguinte é para o grupo de quatro bits, são trocados.
i = (i & 0x0f0f0f0f) << 4 | (I >>> 4) & 0x0f0f0f0f;
A unidade é ligada em octetos, que é, bytes invertida, pode ser escrita como se segue uma forma mais directa, e reverseBytes códigos substancialmente idênticos.
i = (i << 24) | ((i & 0xff00) << 8) | ((i >>> 8) & 0xff00) | (i >>> 24);
Por que escrever o código invertida, para obscurecer-lo? Ou gravação não pode ser mais fácil de compreender a maneira dele? Por exemplo, para alcançar aleta, uma idéia comum é, primeiro e último de câmbio, o segundo e swap penúltima até o meio dos dois troca está completo. Se os dados não são bits binários, a idéia é boa, mas para os bits, a eficiência é relativamente baixa.
instruções da CPU e operação eficiente não pode ser um único bit, a menor unidade de dados que é tipicamente operação de 32 bits (máquinas de 32 bits), mudança Além disso, a CPU pode ser eficientemente implementado e operações lógicas, mas mais lentamente Math.
reverter essas características é a plena utilização da CPU, realizado no câmbio paralelo e eficiente de bits adjacentes, a mesma função também pode ser alcançado em outras maneiras mais fáceis de entender, mas este é mais eficiente do que o código difícil.
mudança cíclica
uso
Integer tem dois métodos estáticos pode ser deslocada ciclicamente:
public static int rotateLeft (int i, distância int) public static int rotateRight (int i, distância int)
rotateLeft é Rodar para a esquerda, rotateRight é girado para a direita, a distância é o número de bits que se deslocam, chamado deslocamento cíclico, o deslocamento é relativo ao normal em termos da mudança geral, tal como à esquerda 2, a parte superior dois originais não existe certo irá preencher 0, e se for deslocada para a esquerda dois ciclos, o topo dois originais irá mover para a direita, como um anel em torno do mesmo contato. Vamos olhar um exemplo:
int a = 0x12345678; int b = Integer.rotateLeft (a, 8); System.out.printlnl (Integer.toHexString (b)); int c = Integer.rotateRight (a, 8); System.out.printlnl (Integer.toHexString (c))
b é um deslocamento para a esquerda circular resultado de 8 bits, c é um deslocamento circular direita de 8 bits resultado, a saída é:
34567812 78.123.456
código de implementação
Código que implementa essas duas funções são:
public static int rotateLeft (int i, distância int) { return (i << distância) | (i >>> -distância); } Public static int rotateRight (int i, int distância) { return (i >>> distância) | (i << -Distância); }
Estas duas funções são intrigantes é negativo, se a distância é de 8, que i >>> - 8 O que significa? Na verdade, o menor número real de passagem à era digital direto não está de volta, mas o valor digital direta de 5, ou é um resultado direto de 0x1f digitais e de. A razão para isso é porque os cinco maiores representam 31, deslocando mais de 31 pares inteiro int é inválido.
Compreender a posição de se mover significado negativo, estamos mais propensos ao código acima, por exemplo, -8 representação binária é:
11111111111111111111111111111000
Seu menor 5 é 11000, o decimal é 24, então eu >>> - 8 é i >>> 24, i << 8 | i >>> 24 é girado para a esquerda, oito.
Código acima, eu >>> - distância é i >>> (32-distância), i << - distância é i << (32 distância).
achado bit a bit, contagem
Há outros pedaços operações inteiras, incluindo:
public static int signum (int i)
Verifique o bit de sinal, retornos positivos 1, -1, 0 retorno negativo 0
public static int lowestOneBit (int i)
Encontre o direito do número de posição do primeiro, que permanecem inalterados, o outro bit é definido como 0, o inteiro é retornado. 3 Por exemplo, binário 11, resultado binário é 01, o decimal é 1, durante 20, é 10.100 binário, o resultado é 00100, é 4 decimal.
public static int highestOneBit (int i)
Olhando a partir do lado esquerdo do primeiro número da posição 1, que se mantêm inalterados, o outro bit é ajustado para 0, o número inteiro é devolvido.
public static int bitCount (int i)
Encontre a representação binária do número 1. 20 Por exemplo, um número binário é 2 10100,1.
numberOfLeadingZeros int public static (int i)
Começando à esquerda é o número de nulos consecutivos. 20 Por exemplo, o binário é 10100, deixou 27 0.
numberOfTrailingZeros int public static (int i)
A extremidade direita é o número de consecutivos 0 do. 20 Por exemplo, o binário é 10100, à direita há dois zero.
Sobre realização do código, existem comentários dirigidos Delight capítulos relevantes do hacker deste livro, não vou repeti-los.
A realização valueOf
Quando mencionamos na seção anterior, criar um objeto de classe wrapper, você pode usar o método valueOf estático, você também pode usar o novo direta, mas recomenda-se usar valueOf, por quê? Nós olhamos código valueOf:
public static Integer valueOf (int i) { assert IntegerCache.high> = 127; se (i> = IntegerCache.low && i <= IntegerCache.high) retornar IntegerCache.cache [i + (-IntegerCache.low)]; voltar new Integer (i); }
Ele usa IntegerCache, que está dentro de um código de classe estática privada da seguinte forma:
classe estática privada IntegerCache { static final int baixa = -128; int static final; cache de Integer static final []; estática { // alto valor pode ser configurado por propriedade int H = 127; Corda integerCacheHighPropValue = sun.misc.VM.getSavedProperty ( "java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue! = null) { int i = parseInt (integerCacheHighPropValue); I = Math.max (i, 127); // máxima dimensão da matriz é Integer.MAX_VALUE h = Math.min (i, Integer.MAX_VALUE - (-baixa) -1); } Elevada = H; cache = new Integer [(alta - baixa) + 1]; j = int baixo; para (int k = 0; k <cache.length; k ++) cache de [k] = new Integer (j ++); } IntegerCache privada () {} }
IntegerCache inteiro representando cache, em que a memória cache é uma matriz estática de variáveis inteiro é inicializado no bloco estático inicializador, por padrão, um dispositivo de armazenamento 127, um total de 256 que corresponde a um número inteiro a partir de -128 a um objeto inteiro.
No código valueOf, se o valor está na faixa de cache de -128 a 127 que é o padrão, então o Integer objeto pré-adquiridos criado directamente a partir da IntegerCache, não só o alcance do cache, o objeto não é criado pelo novo.
Pelo compartilhamento de objetos comuns, você pode economizar espaço de memória, uma vez Integer é imutável, ele é armazenado em cache objetos podem ser seguramente compartilhada. Boolean / Byte / Short / Long / Character tem uma implementação similar. Este objeto comum de partilha de pensamento, é uma idéias de design comuns, em <Modo de design> isso funciona, é dado um nome, chamado Flyweight, o Inglês chamado Flyweight, ou seja, a percentagem de elementos leves.
resumo
Esta seção descreve alguns operacional bit em Integer, código de operação pouco mais obscuro, mas o desempenho é relativamente alto, vamos explicar em detalhe algum código que, se você quiser saber mais sobre, de acordo com comentários, ver Delight este livro de Hacker. Também introduzimos a realização valueOf, introduz o padrão Flyweight.
A próxima seção, vamos explorar Character