Skip to content
Theory · Operators and expressions · lesson 5 of 8

Overflow

Java's calculator drops the fraction in integer division, and that is one of its rules. Another one is about size: every integer type has a limited number of digits.

Think of the odometer in an old car. It has six wheels with digits, and it cannot show more than 999999. Drive one more kilometer, and it shows 000000: the wheels rolled over and started again.

Something similar happens to an int. It holds numbers from about minus two billion to plus two billion. Let's see what happens when you add one to the largest of them:

JAVA
public class Main {
    public static void main(String[] args) {
        int max = Integer.MAX_VALUE;
        System.out.println(max);     // 2147483647
        System.out.println(max + 1); // -2147483648
    }
}

Let's walk through the program line by line:

  1. Integer.MAX_VALUE is a constant from the standard library, the largest int value. The program puts it into max.
  2. System.out.println(max) prints 2147483647.
  3. System.out.println(max + 1) prints -2147483648: the number 2147483648 does not fit in an int, and the value moved to the other end of the range.

No compile error and no exception: the program silently printed a wrong number.

Here the odometer picture parts ways with Java. An odometer has no negative numbers, but an int does. So the maximum is followed not by zero but by the smallest negative number.

The bounds of int

The smallest int value is held by the constant Integer.MIN_VALUE, which equals -2147483648. When a result does not fit in the type's range, an overflow occurs. In Java it is silent in both directions:

  • the minimum comes after the maximum: Integer.MAX_VALUE + 1 equals Integer.MIN_VALUE;
  • the maximum comes below the minimum: Integer.MIN_VALUE - 1 equals Integer.MAX_VALUE;
  • a long behaves the same way, only its bound is further out: Long.MAX_VALUE equals 9223372036854775807.

Interviewers often ask this: what does Integer.MAX_VALUE + 1 give? The answer: Integer.MIN_VALUE, with no error and no exception.

The eight bits of a byte

An int has 32 bits, and watching all of them at once is awkward. The byte type overflows by the same rule, only it has eight bits, and its range is -128 to 127.

Each bit holds a 0 or a 1, and a number in a byte is the sum of the weights of the bits that are set to one. The weights go from right to left: 1, 2, 4 and on up to 64. The leftmost bit has a negative weight, -128, which is why it is called the sign bit: when it is one, the number is negative.

Below, a byte works as a scaled-down model of an int. The x++ button adds one to the number: press it and watch what happens to the sign bit after 127.

Livebyte: eight bitsx = 125

x = 125: a byte has eight bits, and the largest number is 127. Press x++.

Watch the leftmost bit: it weighs −128

In 127, every bit except the sign bit is one: 0111 1111. Adding one carries from right to left all the way to the leftmost bit, and the result is 1000 0000. Only the sign bit is one now, so the number is -128. An int works the same way, only its sign bit weighs -2147483648.

b++ and a cast to byte

The widget's button is labeled x++ for a reason: that is how Java writes "add one to a variable". Let's repeat the same thing in code and also see what a cast to byte does:

JAVA
byte b = 127;
b++;
System.out.println(b);          // -128
System.out.println((byte) 200); // -56
  1. b++ increases the variable by one. The type does not change, so b crosses the bound the same way as in the widget.
  2. (byte) 200 casts an int to a byte. Only the eight lowest bits of the number are kept: 1100 1000. The sign bit is one, so the result is -128 + 64 + 8, that is, -56.

A cast to a smaller integer type does not check the range either: the extra high bits are silently dropped.

How to guard against it

A wrong number is more dangerous than a stopped program: with it, the program goes on counting money or time. There are two ways to guard against overflow:

JAVA
int max = Integer.MAX_VALUE;
long sum = (long) max + 1;
System.out.println(sum);                   // 2147483648
System.out.println(Math.addExact(max, 1));
TEXT
Exception in thread "main" java.lang.ArithmeticException: integer overflow

Calculate in long

A long holds numbers up to 9223372036854775807, so the sum of two int values does not overflow in it. What matters is switching to long before the addition: (long) max + 1 adds two long values and prints 2147483648.

Check with Math.addExact

Math.addExact(a, b) returns the sum if it fits in the type, and otherwise throws an ArithmeticException with the text integer overflow. For subtraction and multiplication there are Math.subtractExact and Math.multiplyExact.

Common mistake

The number of milliseconds in 30 days is stored in a long variable:

JAVA
public class Main {
    public static void main(String[] args) {
        long ms = 30 * 24 * 60 * 60 * 1000; // ✗
        System.out.println(ms);             // -1702967296
    }
}

The variable ms is a long, but every number on the right is an int. So Java multiplies them as int values, the product 2592000000 overflows, and only then does the wrong number go into the long. Put an L on the first number: 30L * 24 * 60 * 60 * 1000 is calculated in long and gives 2592000000.

Key points

  • The bounds of int: Integer.MAX_VALUE equals 2147483647, and Integer.MIN_VALUE equals -2147483648.
  • Overflow is silent: Integer.MAX_VALUE + 1 gives Integer.MIN_VALUE with no error and no exception.
  • The minus comes from the sign bit: in a byte, 127 + 1 gives 1000 0000, that is, -128.
  • You guard against overflow by switching to long before the calculation, as in 30L * …, or with Math.addExact, which throws an ArithmeticException.