Há boas respostas aqui, mas não vejo nenhuma demonstração de operações bit a bit. Como Visser (a resposta atualmente aceita) diz, o Java assina números inteiros por padrão (o Java 8 tem números inteiros não assinados, mas eu nunca os usei). Sem mais delongas, vamos fazê-lo ...
Exemplo RFC 868
O que acontece se você precisar gravar um número inteiro não assinado no IO? Um exemplo prático é quando você deseja exibir o tempo de acordo com a RFC 868 . Isso requer um número inteiro não assinado de 32 bits, big endian, que codifica o número de segundos desde 00:00 de 1º de janeiro de 1900. Como você codificaria isso?
Crie seu próprio número inteiro de 32 bits não assinado como este:
Declarar uma matriz de bytes de 4 bytes (32 bits)
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
Isso inicializa a matriz, consulte As matrizes de bytes são inicializadas como zero em Java? . Agora você precisa preencher cada byte na matriz com informações na ordem big-endian (ou little-endian se você quiser causar estragos). Supondo que você tenha um longo contendo o tempo (inteiros longos têm 64 bits em Java) chamado secondsSince1900
(que utiliza apenas os primeiros 32 bits, e você já lidou com o fato de que Date faz referência a 00:00 em 1º de janeiro de 1970), você pode usar o AND lógico para extrair bits dele e mudar esses bits para posições (dígitos) que não serão ignorados quando colocados em um byte e na ordem big endian.
my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed
my32BitUnsignedInteger
Agora, nosso é equivalente a um número inteiro big endian não assinado de 32 bits que adere ao padrão RCF 868. Sim, o tipo de dados longo é assinado, mas ignoramos esse fato, porque assumimos que os segundosSince1900 usavam apenas os 32 bits inferiores). Por envolver o comprimento em um byte, todos os bits maiores que 2 ^ 7 (dois primeiros dígitos em hexadecimal) serão ignorados.
Fonte referenciada: Java Network Programming, 4ª Edição.