Java не робить нічого із цілим переповненням як для int, так і для довгих примітивних типів і ігнорує переповнення позитивними та негативними цілими числами.
Ця відповідь спочатку описує цілочисельне переповнення, наводить приклад того, як це може статися, навіть із проміжними значеннями в оцінці виразів, а потім дає посилання на ресурси, які дають детальні методи запобігання та виявлення цілочислового переповнення.
Арифметика цілого числа і вирази, що виникають у результаті несподіваного або невиявленого переповнення, є поширеною помилкою програмування. Несподіване або невиявлене переповнення цілих чисел також є добре відомою проблемою безпеки, особливо це стосується об'єктів масиву, стека та списку.
Переповнення може відбуватися у позитивному чи негативному напрямку, коли позитивне чи негативне значення буде перевищувати максимальне або мінімальне значення для відповідного примітивного типу. Переповнення може виникати в проміжному значенні під час вираження або оцінки операції і впливати на результат виразу або операції, коли очікується, що кінцеве значення буде в межах діапазону.
Іноді негативний перелив помилково називається підливом. Underflow - це те, що відбувається, коли значення буде ближче до нуля, ніж дозволяє представлення. Підвищення відбувається в цілій арифметиці і очікується. Підниження цілого числа відбувається, коли ціле оцінювання буде від -1 до 0 або 0 і 1. Який буде дробовий результат скорочується до 0. Це нормально і очікується з арифметикою з цілим числом і не вважається помилкою. Однак це може призвести до викиду коду. Одним із прикладів є виняток "ArithmeticException: / за нулем", якщо результат вираження цілого числа використовується як дільник у виразі.
Розглянемо наступний код:
int bigValue = Integer.MAX_VALUE;
int x = bigValue * 2 / 5;
int y = bigValue / x;
в результаті чого x присвоюється 0, а наступна оцінка bigValue / x кидає виняток, "ArithmeticException: / по нулю" (тобто ділиться на нуль), а не y присвоюється значення 2.
Очікуваний результат для x складе 858,993,458, що менше максимального значення int 2,147,483,647. Однак проміжний результат оцінювання Integer.MAX_Value * 2 буде 4,294,967,294, що перевищує максимальне значення int і дорівнює -2 відповідно до 2-х представлень комплементу. Подальше оцінювання -2 / 5 оцінюється до 0, яке присвоюється x.
Переставляючи вираз для обчислення x на вираз, який при оцінці ділиться перед множенням наступного коду:
int bigValue = Integer.MAX_VALUE;
int x = bigValue / 5 * 2;
int y = bigValue / x;
приводить до того, що x присвоюється 858,993,458, а y присвоюється 2, що очікується.
Проміжний результат від bigValue / 5 становить 429,496,729, що не перевищує максимальне значення для int. Подальша оцінка 429,496,729 * 2 не перевищує максимальне значення для int, і очікуваний результат присвоюється x. Оцінка для y тоді не ділиться на нуль. Оцінки для x та y працюють, як очікувалося.
Цілі значення Java зберігаються як і поводяться відповідно до 2s доповненням підписаних цілих чисел. Коли отримане значення буде більшим або меншим, ніж максимальне або мінімальне ціле значення, натомість виходить ціле ціле значення 2. У ситуаціях, не прямо розроблених для використання поведінки комплементу 2s, що є найбільш звичайною цілою арифметичною ситуацією, отримане значення 2s доповнення спричинить логіку програмування або помилку обчислень, як показано в прикладі вище. Відмінна стаття у Вікіпедії описує тут 2-х компліментарних двійкових цілих чисел: Доповнення двох - Вікіпедія
Існують методи уникнення ненавмисного цілого переповнення. Техніка може бути класифікована як тестування перед умовами, оновлення та BigInteger.
Тестування перед умовою включає вивчення значень, що переходять в арифметичну операцію чи вираз, щоб переконатися, що переповнення не буде з цими значеннями. Програмування та дизайн повинні створити тестування, яке гарантує, що вхідні значення не спричинить переповнення, а потім визначити, що робити, якщо трапляться вхідні значення, які спричинять переповнення.
Оновлення включає використання більшого примітивного типу для виконання арифметичної операції або виразу, а потім визначення, чи отримане значення перевищує максимальне або мінімальне значення для цілого числа. Навіть при оновленнях все одно можливо, що значення або якесь проміжне значення в операції чи виразі буде перевищувати максимальні або мінімальні значення для типу оновлення та спричинити переповнення, яке також не буде виявлено і спричинить несподівані та небажані результати. За допомогою аналізу або попередніх умов можна запобігти переповненню моменту, коли запобігання без оновлення неможливе або практичне. Якщо цілі числа, про які йдеться, вже є довгими примітивними типами, то оновлення неможливо з примітивними типами на Java.
Метод BigInteger включає використання BigInteger для арифметичної операції або вираження за допомогою бібліотечних методів, які використовують BigInteger. BigInteger не переповнює. Він буде використовувати всю наявну пам'ять, якщо необхідно. Його арифметичні методи, як правило, лише дещо менш ефективні, ніж цілі операції. Досі можливо, що результат, що використовує BigInteger, може перевищувати максимальне або мінімальне значення для цілого числа, однак переповнення не буде відбуватися в арифметиці, що веде до результату. Програмування та проектування все одно потрібно буде визначати, що робити, якщо результат BigInteger перевищує максимальні або мінімальні значення для бажаного примітивного типу результату, наприклад, int або long.
Програма CERT Carnegie Mellon Software Engineering Institute та Oracle створили набір стандартів для безпечного програмування Java. До стандартів входять методики запобігання та виявлення цілого переповнення. Стандарт опублікований як вільно доступний інтернет-ресурс тут: Стандарт безпечного кодування CERT Oracle для Java
Розділ стандарту, який описує і містить практичні приклади методів кодування для запобігання або виявлення цілого числа переповнення, знаходиться тут: NUM00-J. Виявити або запобігти цілому переповненню
Форма книги та форма PDF у форматі стандарту безпечного кодування CERT Oracle для Java також доступні.