Хотите верьте, хотите нет, но Java также содержит переполнение целочисленного буфера. Я не уверен, что это правильное слово для описания этого или нет, может быть, вы можете предложить некоторые 🙂
Хорошо, пожалуйста, взгляните на приведенную ниже программу, эта программа выводит количество микросекунд в день.
public class JavaLongOverflow { public static void main(String[] args) { final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000; System.out.println("MICROS_PER_DAY : " + MICROS_PER_DAY); } }
Результат
MICROS_PER_DAY : 500654080
О… ответ таков 500654080 . Подождите… правильный ли ответ? Правильный ответ должен быть 86400000000 !!! Почему Java даст мне неточный результат? откуда взялся этот номер? Что именно произошло?
Я действительно верю, что это вызвано переполнением “int”. Да, переменная “long MICROS_PER_DAY” имеет достаточно места, чтобы вместиться в большое число, например 86400000000, но она не помещается в “int”! Максимальное число “int” равно 2147483647. Внимательно посмотрите на приведенную выше программу, вся арифметика находится в “int”, результат повышен до long и присвоен переменной “long MICROS_PER_DAY”. Согласно [JLS 5.1.2], переход от int к long упоминается как расширяющее примитивное преобразование, которое сохраняет (неверное) числовое значение.
Однако мы можем избежать вышеупомянутого переполнения беззвучного убийцы, явно указав “длинный” в первом целочисленном числе, чтобы заставить всю операцию превратиться в длинную арифметику.
public class JavaLongOverflow { public static void main(String[] args) { final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000; System.out.println("MICROS_PER_DAY : " + MICROS_PER_DAY); } }
Результат
MICROS_PER_DAY : 86400000000
Выше программа печатает 86400000000 как и ожидалось
Вывод
Эту ошибку так трудно обнаружить или осознать. Иногда это даже невозможно обнаружить. Если кто-то совершит подобную ошибку в финансовой системе, я просто не могу представить себе последствия. Мой единственный совет – явно приводить примитивный тип, когда речь идет о вычислении двух разных типов примитивного типа. Всегда избегайте автоматического расширения примитивного преобразования в любом расчете.
Оригинал: “https://mkyong.com/java/javas-silent-killer-buffer-overflow-careful/”