Java 8 - точные математические примеры
Java 8 представила новые методы в классеMath
, которые будут генерироватьArithmeticException
для обработки переполнения. Эти методы состоят изaddExact
,substractExact
,multiplyExact
,incrementExact
,decrementExact
иnegateExact
сint
иlong
аргументы. Кроме того, существует статический методtoIntExact
для преобразования значенияlong
вint
, который также вызываетArithmeticException
.
До Java 8 программист должен был вручную отлаживать, чтобы найти переменные в коде, которые переполняются. Я был очень взволнован, когда узнал, что в Java 8 появился новый набор методов, которые генерируют исключение при переполнении результата. Для многих разработчиков это изменение не имеет большого эффекта, но для скромных разработчиков, таких как я, оно определенно повлияет на время, потраченное на то, чтобы почесать голову, чтобы понять, почему результат неправильный, или на необходимость принятия сложных мер предосторожности, чтобы избежать переполнения.
1. Math.multiplyExact
Этот пример демонстрирует разницу между обычным умножением и новымmultiplyExact
MultiplyExact.java
package com.techfou.exactmethods; package com.techfou; 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"); } } }
Выход:
---Before Java 8--- z : 1 ---Since Java 8--- integer overflow z : 4611686014132420609 > yuuuup z is Long
2. Обнаружение и обработка переполнения
Пример, в котором мы обрабатываем переполнение дляinteger
и определяем переполнение дляlong
.
MultiplyExact2.java
package com.example.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"); } } }
Выход:
---Before Java 8--- z : -727379968 c : 1 ---Since Java 8--- z is instance of Long: 1000000000000 Overflow for c
3. Все методы xxxExact
Пример, демонстрирующий все новые методыxxxExact
AllExactMethods.java
package com.example.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); } }
Выход:
addExact: 10000 + 10000 = 20000 subtractExact: 10000 - 10000 = 0 multiplyExact: 10000 * 10000 = 100000000 incrementExact: 10000 + 1 = 10001 decrementExact: 10000 - 1 = 9999 negateExact: 10000 * -1 = -10000