How do you perform bitwise operations in Kotlin given there are no &, |, ^, <<, >> symbols?
answer
- and / or / xor / inv (NOT) / shl / shr / ushr
- No &, |, ^, ~, <<, >>, >>> symbols
- inv() is a method (unary), the rest are infix
- shr sign-extends, ushr zero-fills
- Int & Long only — convert Byte/Short first
basics
~20 sKotlin uses named functions you write between the values, like a and b, a or b, a xor b, a shl 2, a shr 2. There are no &, |, ^, <<, or >> symbols like in Java.
solid answer
~40 sKotlin deliberately drops C/Java-style bitwise symbols and provides named **infix** functions on Int and Long instead: `and`, `or`, `xor`, `inv` (bitwise NOT, takes no argument), `shl` (signed left shift), `shr` (signed/arithmetic right shift, sign-extends), and `ushr` (unsigned right shift, zero-fills). So Java's `a & b` is `a and b`, `a | b` is `a or b`, `a ^ b` is `a xor b`, `~a` is `a.inv()`, `a << 2` is `a shl 2`, `a >> 2` is `a shr 2`, `a >>> 2` is `a ushr 2`. These are only defined for Int and Long (not Byte/Short — convert first). Because they are ordinary functions, they have lower precedence than arithmetic, so you often need parentheses: `a and 0xFF == x` parses surprisingly — write `(a and 0xFF) == x`.
code
kotlin · 9 linesfun main() {
println(0xF0 and 0x0F) // 0
println(0xF0 or 0x0F) // 255
println(0b1010 xor 0b0110) // 12 (0b1100)
println(0.inv()) // -1 (all bits set)
println(1 shl 4) // 16
println(-8 shr 1) // -4 (sign-extended)
println(-8 ushr 1) // 2147483644 (zero-filled)
}go deeper
Knows you use named words like and/or/shl instead of symbols.
Maps each Java symbol to its Kotlin function and knows inv() is the unary NOT method.
Explains shr vs ushr sign behavior, the Int/Long-only restriction, and infix precedence pitfalls.
Discusses why named operators improve readability/safety, interop with bit-packed Java formats, and when to prefer EnumSet/typed flags over raw masks.
## No symbolic bitwise operators Unlike Java/C, Kotlin has **no** `&`, `|`, `^`, `~`, `<<`, `>>`, `>>>` symbols. Instead it exposes bitwise operations as named **infix functions** declared on `Int` and `Long`: | Java symbol | Kotlin | Meaning | |-------------|--------|---------| | `a & b` | `a and b` | bitwise AND | | `a \| b` | `a or b` | bitwise OR | | `a ^ b` | `a xor b` | bitwise XOR | | `~a` | `a.inv()` | bitwise NOT (one's complement) | | `a << n` | `a shl n` | signed left shift | | `a >> n` | `a shr n` | arithmetic (sign-extending) right shift | | `a >>> n` | `a ushr n` | logical (zero-filling) right shift | `inv` is a **method**, not infix, because it is unary: `0.inv()` -> `-1` (all bits set). ## Shift semantics ```kotlin 1 shl 4 // 16 (1 << 4) -8 shr 1 // -4 sign bit preserved (arithmetic) -8 ushr 1 // 2147483644 zero-filled (logical) 0xF0 and 0x0F // 0 0xF0 or 0x0F // 255 ``` `shr` sign-extends so negative numbers stay negative; `ushr` shifts in zeros from the left, which is why `-8 ushr 1` becomes a large positive number for `Int`. ## Defined only on Int and Long These functions exist for `Int` and `Long` only. `Byte`, `Short`, `Char` do **not** have them — you must `.toInt()` first, operate, and convert back if needed. ## Precedence gotcha Because `and`, `or`, etc. are regular infix functions, they sit at **infix precedence**, which is **lower** than arithmetic and comparison in many configurations and differs from Java's bitwise precedence. Always parenthesize when mixing with `==` or arithmetic: ```kotlin val masked = (flags and MASK) == MASK // parentheses required for intent ``` ## When to use Bitwise infix functions show up in flag/bitmask handling, low-level protocol parsing, hashing, and interop with C/Java bit-packed formats. For typed flag sets, an `enum` + `EnumSet` is usually clearer than raw masks.
- What is the difference between shr and ushr?shr is arithmetic: it preserves the sign bit (sign-extends). ushr is logical: it always shifts zeros in from the left, so negatives become large positives.
- Why is inv() a method while and/or are infix?inv is unary (one operand) so infix syntax wouldn't fit; and/or/xor/shl/shr/ushr are binary and declared with the infix modifier.
saying these in an interview costs you the question
- Trying to use & or | symbols in Kotlin
- Confusing shr and ushr semantics
- Calling inv with an argument like a inv b
- Assuming Byte/Short support these functions directly
- Forgetting parentheses and getting wrong precedence