What happens when an int arithmetic operation exceeds its range, and how do you detect or avoid it?
answer
- Integer overflow WRAPS silently, no exception
- MAX_VALUE + 1 == MIN_VALUE (modulo 2^32)
- Midpoint fix: low + (high - low) / 2
- Math.addExact / multiplyExact throw on overflow
- All-int literals overflow before widening; use an L
basics
~10 sThe value silently wraps around: adding 1 to the maximum int (2147483647) gives the minimum int (-2147483648). Java does not throw an error. Use a long, or Math.addExact to throw on overflow.
solid answer
~40 sJava integer arithmetic is modular and wraps silently — there is no exception by default. Because int is 32-bit two's-complement, Integer.MAX_VALUE + 1 overflows to Integer.MIN_VALUE. A classic real bug is `(low + high) / 2` for a binary-search midpoint overflowing when both are large; the fix is `low + (high - low) / 2`. To avoid overflow, widen to long (or BigInteger for unbounded values), or, if you need to *catch* it, use Math.addExact / multiplyExact / toIntExact, which throw ArithmeticException on overflow. A subtle trap: an expression like `1024 * 1024 * 1024 * 4` overflows because the literals are int — you must make at least one operand a long (`1024L * ...`) so the whole expression is evaluated in long arithmetic.
code
java · 13 linesint max = Integer.MAX_VALUE; // 2147483647
System.out.println(max + 1); // -2147483648 (silent wrap)
// Detect overflow instead of wrapping:
try {
Math.addExact(max, 1);
} catch (ArithmeticException e) {
System.out.println("overflow!"); // this branch runs
}
// Literal trap:
long wrong = 1024 * 1024 * 1024 * 4; // computed in int -> overflows
long right = 1024L * 1024 * 1024 * 4; // computed in long -> 4294967296go deeper
Knows that very large int results 'wrap around' to negative numbers and that you should use long for big values.
Explains modular wraparound at MAX_VALUE, recognizes the all-int-literal trap, and knows long widening as the fix.
Recalls Math.*Exact methods, the binary-search midpoint bug and its fix, and chooses between long, BigInteger, and fail-fast checks based on the call site's risk.
Sets codebase policy for overflow-sensitive domains (money, allocation, indexing), e.g. mandating *Exact or BigDecimal, and weighs performance vs. safety trade-offs across the system.
## The setup: fixed-width integers A Java `int` is **32 bits** wide and stored in **two's-complement** form. Two's-complement is the standard binary encoding for signed integers: the highest (leftmost) bit is the sign bit, and the representable values run from **-2,147,483,648** (`Integer.MIN_VALUE`) to **+2,147,483,647** (`Integer.MAX_VALUE`). Because the width is *fixed*, there are only 2^32 distinct values. ## What overflow is **Overflow** happens when an arithmetic result needs more bits than the type provides. In Java, integer overflow does **not** raise an error or set a flag — it **silently wraps around**, like an odometer rolling past its maximum back to zero. Concretely the result is reduced *modulo 2^32* and reinterpreted as two's-complement: ``` Integer.MAX_VALUE + 1 == Integer.MIN_VALUE // 2147483647 + 1 = -2147483648 Integer.MIN_VALUE - 1 == Integer.MAX_VALUE ``` This is defined, deterministic behavior — not undefined like in C — but it is almost always a *bug* when it happens unexpectedly. ## Two famous traps **1. The binary-search midpoint bug.** Computing the middle index as `(low + high) / 2` overflows when `low + high` exceeds `Integer.MAX_VALUE`, producing a negative index. The classic fix: ```java int mid = low + (high - low) / 2; // never overflows for non-negative low <= high ``` **2. The all-int literal trap.** Each literal below is an `int`, so the *entire* multiplication is done in 32-bit arithmetic and overflows *before* it is assigned to the long: ```java long bytes = 1024 * 1024 * 1024 * 4; // WRONG: overflows to a small/negative int, then widened long ok = 1024L * 1024 * 1024 * 4; // RIGHT: one long operand promotes the whole expression ``` Making the *destination* a `long` does not help; the overflow has already happened on the right-hand side. ## How to detect or avoid it - **Widen the type.** Use `long` (64-bit) when values can grow large, or `BigInteger` for arbitrary precision. - **Fail loudly.** `Math.addExact`, `Math.subtractExact`, `Math.multiplyExact`, `Math.negateExact`, `Math.incrementExact`, and `Math.toIntExact` throw `ArithmeticException` on overflow instead of wrapping. Use them in code where a wrong-but-silent number is dangerous (financial, indexing, allocation sizes). - **Restructure the math** (as in the midpoint example) so the intermediate result stays in range. The same wrapping rules apply to `long` at its own 64-bit boundary; it just takes much larger values to get there.
- Does the same wrapping behavior apply to long?Yes — long is 64-bit two's-complement and wraps at its own boundary (Long.MAX_VALUE + 1 == Long.MIN_VALUE). It just requires far larger magnitudes to overflow.
- How would you compute a sum that might exceed long range?Use BigInteger, which has arbitrary precision and grows as needed, at the cost of object allocation and slower arithmetic than primitives.
saying these in an interview costs you the question
- Believing Java throws an exception on int overflow by default
- Thinking 'long result = int * int' avoids overflow (the int multiply overflows first)
- Saying overflow is undefined behavior (it is well-defined modular wraparound in Java)
- Using (low+high)/2 in interview binary-search code without noticing the overflow