W3docs

Opérateurs bit à bit en Java

Manipulez les bits individuels en Java avec &, |, ^, ~, <<, >> et >>> grâce aux opérateurs bit à bit.

La plupart du code Java ne touche pas aux bits individuels. Mais de temps en temps — regrouper des drapeaux dans un int, lire un format de fichier binaire, calculer un hachage, travailler avec des masques de bits de permission — vous aurez besoin de manipuler des valeurs au niveau des bits. Les opérateurs bit à bit de Java sont le jeu de style C : &, |, ^, ~ et les trois décalages. Ils sont distincts des opérateurs logiques && et ||, qui utilisent le court-circuit et ne fonctionnent qu'avec des valeurs boolean — les opérateurs bit à bit agissent sur chaque bit d'un entier.

Les opérateurs

OpérateurNomCe qu'il fait
&ET (AND)le bit est 1 uniquement si les deux bits sont 1
|OU (OR)le bit est 1 si l'un ou l'autre bit est 1
^OU exclusif (XOR)le bit est 1 si les deux bits sont différents
~NON (complément)inverse tous les bits
<<décalage à gauchedécale les bits vers la gauche, remplit avec 0 à droite
>>décalage à droite signédécale à droite, remplit avec le bit de signe à gauche
>>>décalage à droite non signédécale à droite, remplit avec 0 à gauche

Tous opèrent sur des opérandes int et long. Les types byte, short et char sont d'abord promus en int.

Les littéraux binaires (0b...) facilitent la visualisation des motifs 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)

Notez que Integer.toBinaryString supprime les zéros non significatifs — 6 s'affiche comme 110 et non 0110. Si vous avez besoin d'une largeur fixe pour l'affichage, complétez manuellement.

NOT — ~

~ inverse tous les bits, y compris le bit de signe. Pour un int 32 bits, c'est le complément à deux : ~x est égal à -x - 1 :

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

Les décalages

<< décale vers la gauche, multipliant par des puissances de 2 :

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

>> décale vers la droite en préservant le signe — utile pour diviser des entiers signés :

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

>>> décale vers la droite et remplit toujours avec des zéros — utile quand vous traitez un int comme des bits non signés :

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

Utilisations pratiques

Masques de bits (flags)

Regroupez plusieurs indicateurs oui/non dans un seul 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

C'est la même idée que les permissions de fichiers Unix.

Multiplier ou diviser par des puissances de 2

x << n correspond à x * 2ⁿ ; x >> n correspond à x / 2ⁿ (pour x non négatif) :

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

Le compilateur optimise généralement lui-même les multiplications et divisions simples par des puissances de 2 constantes en décalages, donc écrivez ce qui est le plus lisible.

Échanger deux entiers sans variable temporaire

Un classique avec XOR :

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

Élégant, mais rarement préférable à l'utilisation d'une variable temporaire — les compilateurs modernes gèrent très bien le cas avec temporaire.

Une démonstration

java— editable, runs on the server

Quand utiliser ces opérateurs vs. EnumSet

Pour un petit ensemble fixe de drapeaux en Java moderne, EnumSet<MyFlag> est généralement plus lisible et tout aussi efficace — il stocke les valeurs d'énumération sous forme d'un seul masque de bits long en interne, vous offrant ainsi la lisibilité de Set<MyFlag> avec des opérations rapides au niveau des bits :

enum Permission { READ, WRITE, EXECUTE }

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

Utilisez les opérations bit à bit brutes uniquement lorsque vous manipulez des formats binaires, des registres matériels, ou des chemins critiques où l'empaquetage en int est important.

Prochaine étape

Les chaînes Java — le type référence avec lequel vous travaillerez plus que tout autre.

Pratique

Pratique
Quelle est la valeur de 1 << 4 ?
Quelle est la valeur de 1 << 4 ?
Was this page helpful?