Walk through exactly how Java computes (byte) 257 and (short) 70000, and explain the underlying mechanism.
answer
- Keep low N bits, drop the rest
- Result is value mod 2^N, then signed reinterpret
- Top kept bit = 1 -> negative
- Wrap, not clamp (unlike float->int)
- byte=8 bits, short=16 bits
basics
~20 sJava keeps only the low bits that fit the smaller type and throws the rest away. (byte) 257 is 1 because 257 is 256+1 and only the low 8 bits survive. (short) 70000 is 4464 for the same reason with 16 bits.
solid answer
~40 sInteger-to-integer narrowing in Java is defined as discarding the high-order bits and keeping only the low-order bits that fit the destination, then interpreting that bit pattern as a signed two's-complement number. For (byte) 257: 257 in binary is 1_0000_0001; a byte holds 8 bits, so we keep 0000_0001 = 1. For (short) 70000: a short holds 16 bits; 70000 mod 65536 is 4464, whose 16-bit pattern's top bit is 0, so it stays positive at 4464. Equivalently the result is value mod 2^n reinterpreted as signed, so it can become negative when the kept top bit is 1 (for example (byte) 200 is -56). This is wrap-around, not clamping, which is why range checks matter before narrowing.
code
java · 4 linesSystem.out.println((byte) 257); // 1 (257 mod 256)
System.out.println((byte) 200); // -56 (top bit set -> negative)
System.out.println((short) 70000); // 4464 (70000 mod 65536)
System.out.println((short) 40000); // -25536 (top bit set)go deeper
Recognizes that narrowing an integer can produce an unexpected value and that it is not clamping.
Can compute simple cases with the mod-2^N rule and explain the low-bit-keeping mechanism.
Computes signed results from two's complement by hand and contrasts integer wrap with floating clamp.
Connects defined wrap semantics to safe serialization/hashing patterns and prescribes checked or clamping helpers across a codebase.
## The rule in one sentence When Java narrows one integer type to a smaller integer type, it **keeps only the lowest N bits** (where N is the destination's bit width) and **interprets that bit pattern as a signed two's-complement value**. The higher bits are silently dropped. This is *modular* behavior, not saturation/clamping. ## Prerequisite: binary and two's complement Computers store integers in binary. Java's integer types are **signed two's complement**: - The most significant (leftmost) bit is the sign: 0 = non-negative, 1 = negative. - For an N-bit type, the representable range is -2^(N-1) to 2^(N-1)-1. - byte (N=8): -128..127 - short (N=16): -32768..32767 - To read a two's-complement byte: if the top bit is 1, the value is (bit pattern) - 256. ## Worked example 1: (byte) 257 1. Write 257 in binary (as a 32-bit int): `0000...0001_0000_0001`. 2. A byte keeps the **low 8 bits**: `0000_0001`. 3. Top bit is 0, so it is non-negative: `0000_0001` = **1**. Shortcut: 257 mod 256 = 1, and 1 is in byte range, so the answer is 1. ## Worked example 2: (short) 70000 1. A short keeps the **low 16 bits**. 2^16 = 65536. 2. 70000 mod 65536 = 4464. 3. 4464 in 16 bits is `0001_0001_0111_0000`; top bit 0 -> positive. 4. Result = **4464**. ## When the result goes negative If the kept low bits have their top bit set to 1, the value is negative: - `(byte) 200`: 200 = `1100_1000`. Top bit is 1, so value = 200 - 256 = **-56**. - `(byte) 128`: `1000_0000` = 128 - 256 = **-128**. - `(short) 40000`: 40000 in 16 bits has top bit set, so 40000 - 65536 = **-25536**. ## General formula For narrowing an integer value `v` to an N-bit signed type: ``` r = v mod 2^N // keep low N bits (non-negative remainder) if r >= 2^(N-1): r -= 2^N // reinterpret as signed ``` ## Why this matters - It is **not clamping**. Many developers expect `(byte) 300` to become 127 (byte max). It does not -- it wraps. Relying on clamp behavior is a real bug source. - Hashing, serialization, and byte-buffer code rely on this defined wrap-around, so it is dependable -- just understand it. - To get clamping you must do it yourself, e.g. `(byte) Math.max(-128, Math.min(127, v))`, or use checked conversions for the no-loss case. ## Contrast with floating-to-integer Floating-point narrowing (double -> int) is different: it truncates the fraction and then **clamps** out-of-range magnitudes to MIN/MAX and maps NaN to 0. Integer-to-integer narrowing **wraps** instead. Don't mix the two mental models.
- What is (byte) -130 and why?-130 in 32-bit two's complement has low 8 bits 0111_1110 = 126. So (byte) -130 == 126. The low-bit-keeping rule applies to negatives too: -130 mod 256 = 126.
- How do I narrow to int but clamp instead of wrap?Java has no built-in clamping cast; do it manually, e.g. (int) Math.max(Integer.MIN_VALUE, Math.min(Integer.MAX_VALUE, longVal)), or use Math.toIntExact to throw on overflow rather than clamp.
saying these in an interview costs you the question
- Assuming (short) 70000 clamps to 32767
- Forgetting the sign flip when the top kept bit is 1
- Confusing integer wrap with floating-point clamp behavior