Java Operations ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-07-12

Bitwise and Bit Shift Operators in Java

Bitwise operators work on the individual binary digits of a value rather than on the number as a whole. Java provides four logical bitwise operators — & (AND), | (OR), ^ (XOR), and ~ (NOT) — plus three bit shift operators: <<, >>, and >>>. These operators apply to long, int, short, byte and char.

1. Bitwise Operators: AND, OR, XOR, NOT

The following table lists the bitwise operators available in Java:

Operator Description
~ Bitwise unary NOT operation (NOT, bitwise complement)
& Bitwise binary AND operation (AND, bitwise conjunction)
| Bitwise binary OR operation (OR, bitwise disjunction)
^ Bitwise binary exclusive OR operation (XOR)

Truth table for the four operations:

A B A | B A & B A ^ B ~A
0 0 0 0 0 1
1 0 1 0 1 0
0 1 1 0 1 1
1 1 1 1 0 0

1.1. Bitwise OR (OR, |)

A result bit produced by the OR operator is 1 if the corresponding bit is 1 in at least one of the operands:

  00101010   42
| 00001111   15
  --------------
  00101111   47

1.2. Bitwise AND (AND, &)

A result bit produced by the AND operator, &, is 1 only if the corresponding bits in both operands are also 1. In every other case the result bit is 0:

  00101010   42
& 00001111   15
  --------------
  00001010   10

1.3. Bitwise Exclusive OR (XOR, ^)

A result bit produced by the XOR operator, ^, is 1 if the corresponding bit is 1 in exactly one of the operands. In every other case the result bit is 0:

  00101010   42
^ 00001111   15
  --------------
  00100101   37

1.4. Bitwise NOT (NOT, ~)

The unary NOT operator, ~, also called the bitwise complement, inverts every bit of its operand:

~ 00101010   42
--------------
  11010101

Let's see how bitwise operations work in a program. The following example also shows Integer.toBinaryString(), which returns the binary representation of a decimal value:

public class BitwiseExample1 {
    public static void main(String[] args) {
        int a = 3;
        int b = 6;
        int c = a | b;
        int d = a & b;
        int e = a ^ b;
        int f = ~b;
        System.out.println("a = " + Integer.toBinaryString(a));
        System.out.println("b = " + Integer.toBinaryString(b));
        System.out.println("a | b = " + Integer.toBinaryString(c));
        System.out.println("a & b = " + Integer.toBinaryString(d));
        System.out.println("a ^ b = " + Integer.toBinaryString(e));
        System.out.println("~ b = " + Integer.toBinaryString(f));
    }
}

Program output (toBinaryString() does not print leading zeros):

a = 11
b = 110
a | b = 111
a & b = 10
a ^ b = 101
~ b = 11111111111111111111111111111001

2. Bit Shift Operators: >>, >>> and <<

Bit shift operators move all binary digits of a value a given number of positions:

Operator Name What happens to the bits
<< Left shift Bits move left; zeros are filled in on the right
>> Right shift (arithmetic) Bits move right; the sign bit is copied on the left — the sign is preserved
>>> Unsigned right shift (zero-fill) Bits move right; zeros are filled in on the left regardless of sign

General form:

value << amount

Examples:

34<<3, 56>>2, 78>>>1

To understand how a shift works, it helps to look at binary numbers directly:

0001<<1 = 0010
0100>>1 = 0010

The difference between >> and >>> shows up when shifting negative numbers. The >> operator propagates the sign (leftmost) bit to the right, while >>> fills the vacated positions with zeros. For positive numbers the result of both operations is the same:

int i = 192;
i       00000000 00000000 00000000 11000000 (192)
i<<1    00000000 00000000 00000001 10000000 (384)
i>>1    00000000 00000000 00000000 01100000 (96)
i>>>1   00000000 00000000 00000000 01100000 (96)

int i = -192; (two's complement representation)
i       11111111 11111111 11111111 01000000 (-192)
i<<1    11111111 11111111 11111110 10000000 (-384)
i>>1    11111111 11111111 11111111 10100000 (-96)
i>>>1   01111111 11111111 11111111 10100000 (2147483552)

Note

For a negative number, >>> clears the sign bit, so the result is always a large positive number: -192 >>> 1 yields 2147483552, not "minus 96 unsigned". If you need to divide a negative number by a power of two while keeping its sign, use >>.

Types byte and short are promoted to int when the expression is evaluated. The following example shows what this leads to:

public class BitwiseExample2 {
    public static void main(String[] args) {
        byte a = 64; //0100 0000
        byte b;
        int i = a << 2; // 1 0000 0000
        b = (byte) (a << 2); //0000 0000
        System.out.println("a = " + a);
        System.out.println("i = " + i);
        System.out.println("b = " + b);
    }
}

Program output:

a = 64
i = 256
b = 0

Important

The result of a << 2 has type int, even though a is declared as byte or short. The value 256 fits in an int, but casting it back to byte discards the high-order bits — leaving 0. Assigning the result to a byte without a cast won't compile: byte b = a << 2; fails.

3. Bitwise Assignment Operators

Each bitwise operator has a corresponding compound assignment operator:

Operator Description Equivalent to
&= Bitwise AND assignment x &= y  →  x = x & y
|= Bitwise OR assignment x |= y  →  x = x | y
^= Bitwise XOR assignment x ^= y  →  x = x ^ y
>>= Right shift assignment x >>= n  →  x = x >> n
>>>= Unsigned right shift assignment x >>>= n  →  x = x >>> n
<<= Left shift assignment x <<= n  →  x = x << n

There is one nuance: compound assignment performs an implicit cast to the type of the variable. That's why byte b = 64; b <<= 2; compiles (and, per the rule above, produces 0), while b = b << 2; is a compile error.

4. Practical Uses of Bitwise Operators

Bitwise operators have a fairly wide range of practical applications. Let's look at a few cases.

4.1. Checking Whether a Number Is Even

The expression x & 1 checks whether a number is even: an even number has its lowest bit equal to 0, an odd number has it equal to 1. The parentheses in (x & 1) == 0 are required — because & has lower precedence than ==, without them the expression would be parsed as x & (1 == 0) and would not compile.

4.2. Multiplying and Dividing a Number by Two

  • x<<1 – multiplies by 2;
  • x>>1 – divides by two, discarding any remainder.

Each additional shift position is one more multiplication or division by 2. For negative numbers, x>>1 rounds down rather than toward zero, so the result can differ from x/2: -5 >> 1 equals -3, while -5/2 equals -2.

4.3. Encrypting a Number

Applying the XOR operator twice to the same bit pattern restores its original value. This can be used to encrypt data sent over a network:

C = A ^ B
A = C ^ B

Suppose you need to send a number, 560 — a bank card PIN — in a message. If an attacker intercepts it, they'll learn the PIN and could use it. To prevent this, agree on some number in advance — a mask — with the recipient. Before sending, encrypt the PIN with the bitwise XOR operation: message ^ mask — and send the result. Even if an attacker intercepts the message, they won't know how to decrypt it. The recipient recovers the PIN using the shared mask: codedMessage ^ mask.

The following code illustrates this:

public class BitwiseExample3 {
    public static void main(String[] args) {
        int message = 560;
        int mask = 67;
        int codedMessage = message ^ mask;
        int receivedMessage = codedMessage ^ mask;
        System.out.println("message = " + message);
        System.out.println("message = " + Integer.toBinaryString(message));
        System.out.println("codedMessage = " + codedMessage);
        System.out.println("codedMessage = " + Integer.toBinaryString(codedMessage));
        System.out.println("receivedMessage = " + receivedMessage);
        System.out.println("receivedMessage = " + Integer.toBinaryString(receivedMessage));
    }
}

Program output — after XOR-ing again with the same mask, the recipient sees the original 560:

message = 560
message = 1000110000
codedMessage = 627
codedMessage = 1001110011
receivedMessage = 560
receivedMessage = 1000110000

4.4. Applying a Bit Mask

A mask lets you extract only specific bits from a sequence. For example, take the mask 00100100. It extracts from a sequence only the bits that are set in it — in this case, the 3rd and 6th bit. To do this, simply perform a bitwise AND between the mask and the chosen number:

  001010101
& 000100100
  --------------
  000000100

Frequently Asked Questions

Where are bitwise operators used in real code?

Most often for bit flags and masks: a single int field can store up to 32 settings, a flag is checked with &, set with |, and cleared with & ~. Bitwise operators also show up in network protocols and binary file formats, in color handling (extracting RGB channels), in hash functions, and in cryptography. Even the standard library uses them: HashMap computes its bucket index as (n - 1) & hash.

What is the difference between >> and >>> in Java?

The >> operator is an arithmetic shift: the sign bit is copied in on the left, so the sign of the number is preserved. The >>> operator is an unsigned shift: zeros are always filled in on the left. For positive numbers the results are identical, but for negative numbers they differ sharply: -192 >> 1 gives -96, while -192 >>> 1 gives 2147483552, because the sign bit is cleared and the number becomes a large positive value.

Why does ~x equal -x - 1?

Because of the two's complement representation Java uses to store integers: the negative of a number is obtained by inverting all its bits and adding one, that is, -x == ~x + 1. Rearranging gives ~x == -x - 1. Easy to verify: ~42 equals -43, and ~0 equals -1 (all 32 bits become ones).

How do you check whether a number is even with a bitwise operator?

With the expression (x & 1) == 0 — it is true for even numbers. The mask 1 keeps only the lowest bit, which is 0 for even numbers and 1 for odd ones. This also works correctly for negative numbers, thanks to two's complement. The parentheses around x & 1 are required: & has lower precedence than ==, and without them the expression won't compile.

Comments

Please log in or register to have a possibility to add comment.