Java 8 introduced new methods in the Math class that will throw an ArithmeticException to handle overflows. These methods consist of addExact, substractExact, multiplyExact, incrementExact, decrementExact and negateExact with int and long arguments. In addition, there’s a static toIntExact method to convert a long value to an int that also throws ArithmeticException.

Before Java 8 the programmer had to manually debug to find the variables in the code that overflow. I was quite excited to find out that Java 8 introduced a new set of methods that throw an exception when the result overflows. For many developers this change doesn’t have a major effect, but for humble developers like myself, it will certainly affect the time spent scratching our heads to understand why the result is wrong or having to take complicated precautions to dodge an overflow.

1. Math.multiplyExact

This example demonstrates the difference between common multiplication and the new multiplyExact

MultiplyExact.java

package com.mkyong.exactmethods;

package com.mkyong;

public class MultiplyExact {

    public static void main(String[] args) {

        int x = Integer.MAX_VALUE; //( = 2 147 483 647)
        int y = Integer.MAX_VALUE;
        Object z;

        System.out.println("---Before Java 8---");
        z = x * y;
        System.out.println("z : " + z);

        System.out.println("\n---Since Java 8---");
        try {

            z = Math.multiplyExact(x, y);

        } catch (ArithmeticException e) {

            System.out.println(e.getMessage()); //Java 8 throws integer overflow

            z = Math.multiplyExact((long) x, (long) y);
            System.out.println("z : " + z);
        }

        if (z instanceof Long) {
            System.out.println("\n> yuuuup z is Long");
        }
    }
}

Output:


---Before Java 8---
z : 1

---Since Java 8---
integer overflow
z : 4611686014132420609

> yuuuup z is Long

2. Detect and handle the overflow

An example where we handle the overflow for integer and determine the overflow for long.

MultiplyExact2.java

package com.mkyong.exactmethods;

public class MultiplyExact2 {

    public static void main(String[] args) {

        int x = 1000000;
        int y = 1000000;
        long a = Long.MAX_VALUE; //( = 9 223 372 036 854 775 807)
        long b = Long.MAX_VALUE;
        Object z, c;

        System.out.println("---Before Java 8---");
        z = x * y;
        c = a * b;
        System.out.println("z : " + z);
        System.out.println("c : " + c);

        System.out.println("\n---Since Java 8---");
        try {
            z = Math.multiplyExact(x, y);
            c = Math.multiplyExact(a, b);
        } catch (ArithmeticException e) {
            try {
                z = Math.multiplyExact((long) x, (long) y);
                c = null;
            } catch (ArithmeticException ex) {
                z = null;
            }
        }

        if (z instanceof Integer) {
            System.out.println("z is instance of Integer: " + z);
        }
        if (z instanceof Long) {
            System.out.println("z is instance of Long: " + z);
        } else {
            System.out.println("Overflow for z");
        }

        if (c instanceof Integer) {
            System.out.println("Instance of Integer: " + c);
        }
        if (c instanceof Long) {
            System.out.println("Instance of Long: " + c);
        } else {
            System.out.println("Overflow for c");
        }
    }
}

Output:


---Before Java 8---
z : -727379968
c : 1

---Since Java 8---
z is instance of Long: 1000000000000
Overflow for c

3. All xxxExact methods

An example demonstrating all the new xxxExact methods

AllExactMethods.java

package com.mkyong.exactmethods;

public class AllExactMethods {
	
	public static void main(String[] args){
		int x = 10000;
		int y = 10000;
		Object z;
		
		z = Math.addExact(x, y);
		System.out.println("addExact: " + x + " + " + y + " = " + z);
		z = Math.subtractExact(x, y);
		System.out.println("subtractExact: " + x + " - " + y + " = " + z);
		z = Math.multiplyExact(x, y);
		System.out.println("multiplyExact: " + x + " * " + y + " = " + z);
		z = Math.incrementExact(x);
		System.out.println("incrementExact: " + x + " + 1 = " + z);
		z = Math.decrementExact(y);
		System.out.println("decrementExact: " + y + " - 1 = " + z);
		z = Math.negateExact(x);
		System.out.println("negateExact: " + x + " * -1 = " + z);
	}
}

Output:


addExact: 10000 + 10000 = 20000
subtractExact: 10000 - 10000 = 0
multiplyExact: 10000 * 10000 = 100000000
incrementExact: 10000 + 1 = 10001
decrementExact: 10000 - 1 = 9999
negateExact: 10000 * -1 = -10000

References

  1. “Java 8 in Action” by Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft
  2. Math – Java 8 API