Java Integer Overflow: Patterns, Pitfalls, and Safe Code

June 18, 20268 min read
dsaalgorithmsinterview-prepjava
Java Integer Overflow: Patterns, Pitfalls, and Safe Code
TL;DR
  • Java integer overflow wraps silently using two's complement — Integer.MAX_VALUE + 1 becomes Integer.MIN_VALUE with no exception thrown.
  • The binary search mid-point bug (lo + hi) / 2 overflows when both bounds are large; the fix is lo + (hi - lo) / 2.
  • Cast before multiplying: (long) a * b is correct; (long)(a * b) is too late because the overflow already happened in int arithmetic.
  • Integer.MIN_VALUE cannot be negated safely in 32-bit arithmetic — widen to long first with Math.abs((long) x).
  • Math.addExact / multiplyExact (Java 8+) throw ArithmeticException on overflow instead of silently wrapping.
  • Use BigInteger when values exceed Long.MAX_VALUE, such as factorials of 21 and above.
  • Long literals require the L suffix (3_000_000_000L), and promotion to long must happen before arithmetic, not after.

Java's arithmetic looks normal until your binary search returns a negative mid-point or your area calculation produces a negative number for a 50,000-by-50,000 grid. Both bugs are silent. No exception. No warning. Just the wrong answer, quietly delivered with a smile.

Java integer overflow is one of the most common sources of subtle bugs in coding interviews, and interviewers know exactly which patterns trigger it. This guide covers what each numeric type can hold, the four traps that show up constantly, and the three reliable ways to fix them. See also the int32 vs int64 deep dive and the Java coding interview pitfalls list.


int Holds Two Billion. Then What?

Java has four signed integer primitives. In an interview you will mostly care about two.

TypeBitsMinMax
byte8-128127
short16-32,76832,767
int32-2,147,483,6482,147,483,647
long64-9,223,372,036,854,775,8089,223,372,036,854,775,807

int is what Java defaults to for integer literals and local variables. long is the upgrade you reach for when the math might exceed two billion. BigInteger is the nuclear option when even a long is not enough.

Two constants worth memorizing cold:

Integer.MAX_VALUE // 2_147_483_647 (~2.1 billion) Long.MAX_VALUE // 9_223_372_036_854_775_807 (~9.2 quintillion)

The JVM Is Fine. Everything Is Fine.

Java does not throw an exception when integer arithmetic overflows. It wraps.

This is two's complement arithmetic. When you increment Integer.MAX_VALUE by one, you get Integer.MIN_VALUE. The bits roll over like an odometer, except instead of starting the road trip over, you have a negative array index and a very confused binary search.

int x = Integer.MAX_VALUE; System.out.println(x + 1); // -2147483648

No error. No crash. A perfectly plausible-looking negative number, delivered with total confidence. That is what makes overflow genuinely dangerous in interviews: your code compiles, your test cases with small inputs pass, and the bug only surfaces at scale or with specific edge-case values. The interviewer has seen this exact bug a hundred times and is watching to see if you have too.

Java integer overflow: try block with burning room, catch block with dog saying "THIS IS FINE."

Java's overflow behavior in one image. The catch block never fires. The dog just keeps sipping coffee.


Four Traps Interviewers Know About

The Binary Search Mid-Point

This is the most famous overflow bug in software history. It lived undetected in Java's own standard library for nine years. The classic form:

int mid = (lo + hi) / 2;

If lo and hi are both large, their sum overflows an int. The result is negative. Your mid ends up pointing at a negative index. The code fails on arrays over a billion elements, and the interviewer circles it in red.

The fix is now standard, though plenty of candidates still write the broken form first:

int mid = lo + (hi - lo) / 2;

Or if you are searching within a long range:

long mid = lo + (hi - lo) / 2;

The binary search bugs guide has more on off-by-one and boundary mistakes alongside this overflow trap.

Multiplying Two Ints

Grid area, total product, hash values. Any time you multiply two numbers that could individually approach one billion, the product can exceed Integer.MAX_VALUE.

int rows = 50_000; int cols = 50_000; int area = rows * cols; // -1794967296. Wrong.

The fix is to cast one operand to long before the multiplication:

long area = (long) rows * cols; // 2500000000. Correct.

You must cast before the multiply. Casting the result after is too late because the overflow already happened in int arithmetic.

long bad = (long)(rows * cols); // still wrong, overflow happens first long good = (long) rows * cols; // correct, promotes to long before multiply

isEven function using recursive number * number, a subtle integer overflow bug

Looks reasonable. number * number overflows for anything over 46,340. The recursion then either terminates with the wrong answer or blows the stack. Elegant.

The Integer.MIN_VALUE Negation Bug

Negating Integer.MIN_VALUE overflows because the positive counterpart does not exist in 32-bit two's complement.

int x = Integer.MIN_VALUE; // -2147483648 System.out.println(-x); // -2147483648 -- same number, not positive Math.abs(x); // also -2147483648

This shows up in problems involving absolute values or palindrome checks on negative numbers. If you need to negate safely, widen to long first.

long safeAbs = Math.abs((long) x);

This connects directly to two's complement representation: in a 32-bit signed integer, the negative range has one extra value the positive range cannot represent. There is no +2147483648 in int. It just does not exist.

Long Literal Typos

Java treats numeric literals as int by default. For literals too large for an int, the compiler refuses:

long timestamp = 3_000_000_000; // compile error long timestamp = 3_000_000_000L; // correct

The compiler catches the obviously oversized case. The sneakier version: you multiply two ints and assign to a long. The multiplication happens in int arithmetic first, overflows, and the already-wrong value is widened.

int a = 100_000; int b = 30_000; long bad = a * b; // overflow: computed as int, then widened long good = (long) a * b; // correct

The L suffix is not optional for large literals. Neither is the cast-before-multiply pattern.


Three Ways to Fix It

Cast to Long

The cheapest fix. For most interview problems, promoting to long before the risky operation is enough.

long product = (long) a * b; long sum = (long) a + b; // Convert back if you need int int safe = Math.toIntExact(product); // throws ArithmeticException if it doesn't fit

long arithmetic is just as fast as int on any 64-bit JVM. There is no performance reason to avoid it in an interview. Use it freely.

Math.addExact and Friends (Java 8+)

Java 8 added checked arithmetic methods that throw ArithmeticException on overflow instead of wrapping silently.

Math.addExact(a, b); // throws on overflow Math.subtractExact(a, b); Math.multiplyExact(a, b); Math.toIntExact(longVal); // throws if longVal doesn't fit in int

You would not wrap every operation in addExact during an interview. But Math.toIntExact is genuinely useful when you compute something in long and need to return an int to match the signature.

BigInteger

BigInteger holds integers of arbitrary precision and never overflows. The trade-off: slower than primitive arithmetic, requires object allocation, and uses method calls instead of operators.

BigInteger a = BigInteger.valueOf(Long.MAX_VALUE); BigInteger b = BigInteger.valueOf(Long.MAX_VALUE); BigInteger sum = a.add(b); long result = sum.longValueExact(); // throws if it doesn't fit

Reach for BigInteger when the problem explicitly involves numbers too large for long. Factorial of 21 and above (21! exceeds Long.MAX_VALUE), arbitrary-precision arithmetic, or inputs passed as digit strings. One gotcha that trips people up: compare BigInteger values with .equals() or .compareTo(), never ==.


When to Switch From int to long

Use long when:

  • Array dimensions multiply together (2D grid total elements)
  • Prefix sums where individual values are in the thousands or millions
  • Any hash or checksum computation
  • Timestamps, byte counts, or distances that exceed two billion
  • The problem says "the answer may be very large" without specifying modular arithmetic

The rule of thumb: if two int values can both realistically reach 50,000, their product needs a long.


Quick Reference

SituationFix
Binary search mid-pointlo + (hi - lo) / 2
Multiplying two ints(long) a * b
Summing many intsaccumulate in long
Negating Integer.MIN_VALUEguard with if (x == Integer.MIN_VALUE)
Long literalappend L suffix
Result must fit in intMath.toIntExact(longResult)
Numbers bigger than longBigInteger

Catch It Before the Interviewer Does

Overflow awareness signals proactive edge case thinking. The candidates who catch it are the ones who, when they see multiplication or large index arithmetic, immediately ask "could this overflow?" The ones who miss it write the bug, watch a test case fail, and only then trace back to the root cause. By then the interviewer has already noted it.

SpaceComplexity runs voice-based mock interviews where the interviewer pushes on edge cases like this in real time, so you practice catching overflow before it gets pointed out.

The habit to build: whenever you write a + b or a * b in Java, ask what the maximum value either operand could take, and whether the result fits. It takes two seconds. It is the kind of thing that separates the candidates who just solve the problem from the candidates who solve it and explain why it is correct.


Further Reading