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:
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:
Integer.MAX_VALUEis a constant from the standard library, the largestintvalue. The program puts it intomax.System.out.println(max)prints2147483647.System.out.println(max + 1)prints-2147483648: the number2147483648does not fit in anint, 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 + 1equalsInteger.MIN_VALUE; - the maximum comes below the minimum:
Integer.MIN_VALUE - 1equalsInteger.MAX_VALUE; - a
longbehaves the same way, only its bound is further out:Long.MAX_VALUEequals9223372036854775807.
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.
x = 125: a byte has eight bits, and the largest number is 127. Press x++.
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:
byte b = 127;
b++;
System.out.println(b); // -128
System.out.println((byte) 200); // -56b++increases the variable by one. The type does not change, sobcrosses the bound the same way as in the widget.(byte) 200casts anintto abyte. 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:
int max = Integer.MAX_VALUE;
long sum = (long) max + 1;
System.out.println(sum); // 2147483648
System.out.println(Math.addExact(max, 1));Exception in thread "main" java.lang.ArithmeticException: integer overflowCalculate 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:
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_VALUEequals2147483647, andInteger.MIN_VALUEequals-2147483648. - Overflow is silent:
Integer.MAX_VALUE + 1givesInteger.MIN_VALUEwith no error and no exception. - The minus comes from the sign bit: in a
byte,127 + 1gives1000 0000, that is,-128. - You guard against overflow by switching to
longbefore the calculation, as in30L * …, or withMath.addExact, which throws anArithmeticException.