- Compact Profiles
- Unsigned Integer API
- Integer Arithmetic Overflow/Underflow Detection API
Integer Arithmetic Overflow/Underflow Detection API
Java's primitive integer types store their values in finite numbers of bits (such as 32 bits for an int). When an integer arithmetic operation (such as addition with integer operands) generates a result that cannot fit into these bits, the operation is said to overflow (exceed the largest positive value that can be stored) or underflow (exceed the smallest negative value that can be stored).
Java's integer arithmetic operators don't detect overflows or underflows. Unless an application has been designed to detect these conditions, problems could occur. For example, perhaps a purchase order total calculation (the total is stored as a count of pennies in an integer variable) overflows, which shifts the total from a positive value to a negative value, returning money to the customer along with his or her purchases.
Listing 3 presents an application that demonstrates how you might check for potential overflow or underflow when adding two integers.
Listing 3: IAOUDDemo.java (Version 1).
public class IAOUDDemo { public static void main(String[] args) { int amount = 20; int total = 0; // int total = Integer.MAX_VALUE; total += amount; if ((amount ^ total) < 0) throw new ArithmeticException("integer overflow"); System.out.printf("Total: %d%n", total); amount = -20; total = 0; // total = Integer.MIN_VALUE; total += amount; if ((amount ^ total) < 0) throw new ArithmeticException("integer underflow"); System.out.printf("Total: %d%n", total); } }
Expression (amount ^ total) < 0 evaluates to true when amount and total have opposite signs—an overflow or underflow has occurred. When either condition happens, java.lang.ArithmeticException is instantiated with an appropriate message and thrown.
Compile Listing 3 (javac IAOUDDemo.java) and run the application (java IAOUDDemo). You should observe the following output:
Total: 20 Total: -20
To generate an overflow or underflow, comment out int total = 0; or total = 0; and uncomment int total = Integer.MAX_VALUE; or total = Integer.MIN_VALUE; and then compile and run the program. This time, you should see a thrown exception in the output.
Because writing overflow-/underflow-checking code in potentially many places is a tedious and error-prone exercise, Java SE 8 has removed this burden from you by adding the following methods to the java.lang.Math class:
- public static int addExact(int x, int y)
- public static long addExact(long x, long y)
- public static int decrementExact(int a)
- public static long decrementExact(long a)
- public static int incrementExact(int a)
- public static long incrementExact(long a)
- public static int multiplyExact(int x, int y)
- public static long multiplyExact(long x, long y)
- public static int negateExact(int a)
- public static long negateExact(long a)
- public static int subtractExact(int x, int y)
- public static long subtractExact(long x, long y)
- public static int toIntExact(long value)
These methods perform integer arithmetic operations on their argument(s). When an operation overflows/underflows, ArithmeticException is thrown. Listing 4 provides a demonstration of addExact().
Listing 4: IAOUDDemo.java (Version 2).
public class IAOUDDemo { public static void main(String[] args) { int amount = 20; int total = 0; // int total = Integer.MAX_VALUE; total = Math.addExact(total, amount); System.out.printf("Total: %d%n", total); amount = -20; total = 0; // total = Integer.MIN_VALUE; total = Math.addExact(total, amount); System.out.printf("Total: %d%n", total); } }
Listing 4 is a simpler version of Listing 3 that replaces the addition operation and overflow-/underflow-checking code with calls to addExact(). The application defaults to the same output as Listing 3. Comment out int total = 0; or total = 0; and uncomment its commented-out alternate to observe overflow or underflow—in either case the exception's message is integer overflow.
Conclusion
Although they're not as sexy as lambdas, many developers will equally welcome compact profiles, the Unsigned Integer API, and the Integer Arithmetic Overflow/Underflow Detection API. Compact profiles are Oracle's first response to the Java community's desire for a more modular Java. The new unsigned integer and overflow/underflow detection APIs obviate the need for libraries (such as Google Guava) that include these features.