W3docs

Operadores Bitwise em Java

Manipule bits individuais em Java com os operadores bitwise &, |, ^, ~, <<, >> e >>>.

A maioria do código Java não manipula bits individuais. Mas de vez em quando — ao empacotar flags em um int, ler um formato de arquivo binário, calcular um hash, trabalhar com bitmasks de permissão — você precisará manipular valores no nível de bits. Os operadores bitwise do Java são o conjunto estilo C: &, |, ^, ~ e os três shifts. Eles são distintos dos operadores lógicos && e ||, que fazem short-circuit e só funcionam com valores boolean — os operadores bitwise atuam em cada bit de um inteiro.

Os operadores

OperadorNomeO que faz
&ANDo bit é 1 somente se ambos os bits forem 1
|ORo bit é 1 se qualquer um dos bits for 1
^XORo bit é 1 se os dois bits forem diferentes
~NOT (complemento)inverte todos os bits
<<shift à esquerdadesloca bits à esquerda, preenchendo com 0 à direita
>>shift à direita com sinaldesloca à direita, preenchendo com o bit de sinal
>>>shift à direita sem sinaldesloca à direita, preenchendo com 0 à esquerda

Todos operam em operandos int e long. byte, short e char são promovidos para int primeiro.

Literais binários (0b...) facilitam a visualização dos padrões de bits:

int a = 0b1100;   // 12
int b = 0b1010;   // 10

System.out.println(Integer.toBinaryString(a & b));   // 1000  (8)
System.out.println(Integer.toBinaryString(a | b));   // 1110  (14)
System.out.println(Integer.toBinaryString(a ^ b));   // 110   (6)

Note que Integer.toBinaryString omite zeros à esquerda — 6 é exibido como 110, não 0110. Se você precisar de uma largura fixa para exibição, adicione o preenchimento manualmente.

NOT — ~

~ inverte todos os bits, incluindo o bit de sinal. Para int de 32 bits, isso é complemento de dois: ~x equivale a -x - 1:

System.out.println(~0);    // -1
System.out.println(~5);    // -6
System.out.println(~-1);   // 0

Shifts

<< desloca à esquerda, multiplicando por potências de 2:

System.out.println(1 << 0);   // 1
System.out.println(1 << 1);   // 2
System.out.println(1 << 4);   // 16

>> desloca à direita, preservando o sinal — útil para dividir inteiros com sinal:

System.out.println(16 >> 2);   // 4
System.out.println(-16 >> 2);  // -4   — sign extended

>>> desloca à direita e sempre preenche com zero — útil quando você está tratando um int como bits sem sinal:

System.out.println(-1 >>> 28);  // 15
System.out.println(-1 >> 28);   // -1

Usos práticos

Bitmasks de flags

Empacote várias flags sim/não em um único int:

final int READ    = 1 << 0;  // 0001
final int WRITE   = 1 << 1;  // 0010
final int EXECUTE = 1 << 2;  // 0100

int perms = READ | WRITE;             // set both

boolean canRead    = (perms & READ) != 0;     // true
boolean canExecute = (perms & EXECUTE) != 0;  // false

perms |= EXECUTE;       // grant execute
perms &= ~WRITE;        // revoke write
perms ^= READ;          // toggle read

Essa é a mesma ideia das permissões de arquivo Unix.

Multiplicar ou dividir por potências de 2

x << n equivale a x * 2ⁿ; x >> n equivale a x / 2ⁿ (para x não negativo):

int doubled = x << 1;
int halved  = x >> 1;

O compilador geralmente otimizará por conta própria multiplicações e divisões simples por potências de 2 constantes para shifts, portanto escreva o que for mais claro.

Trocar dois ints sem variável temporária

Um truque clássico com XOR:

int a = 5, b = 3;
a ^= b;
b ^= a;
a ^= b;
System.out.println(a + " " + b);   // 3 5

Elegante, mas raramente vale a pena usar em vez de uma variável temporária — compiladores modernos lidam bem com o caso da variável temporária.

Uma demonstração

java— editable, runs on the server

Quando usar estes vs. EnumSet

Para um pequeno conjunto fixo de flags no Java moderno, EnumSet<MyFlag> costuma ser mais claro e igualmente eficiente — ele armazena valores de enum como um único bitmask long internamente, então você obtém a legibilidade de Set<MyFlag> com operações rápidas no nível de bits:

enum Permission { READ, WRITE, EXECUTE }

EnumSet<Permission> perms = EnumSet.of(Permission.READ, Permission.WRITE);
perms.add(Permission.EXECUTE);
perms.contains(Permission.READ);   // true

Recorra a operações de bits brutas somente quando estiver lidando com formatos binários, registradores de hardware ou caminhos críticos onde o empacotamento com int importa.

O que vem a seguir

Java Strings — o tipo de referência com o qual você trabalhará mais do que qualquer outro.

Prática

Prática
Qual é o resultado de 1 << 4?
Qual é o resultado de 1 << 4?
Was this page helpful?