Арит переполнения в Java: почему нет исключений во время выполнения и нет предупреждений компилятора? - PullRequest
4 голосов
/ 19 февраля 2012

Я знаю, что на этот вопрос частично ответили здесь, на SO , но там они объясняют , что происходит во время арифметического переполнения.А в других местах на SO они объясняют, как проверить переполнение в Java-коде, то есть предотвратить его как программиста.

Здесь я спрашиваю , почему нет никаких исключений во время выполнения и нет предупреждений компилятора ?

AFAIK, на это раньше не отвечали.

В книге Брюса Эккеля Мышление на Яве , 1-е изд.(2000), глава 3, есть эта небольшая Java-программа:

//: Overflow.java
// Surprise! Java lets you overflow.
public class Overflow {
      public static void main(String[] args) {
        int big = 0x7fffffff; // max int value
        prt("big = " + big);
        int bigger = big * 4;
        prt("bigger = " + bigger);
      }
      static void prt(String s) {
        System.out.println(s);
      }
} ///:~

Вывод этого:

big = 2147483647
bigger = -4

, и вы не получите ошибок или предупреждений откомпилятор, и никаких исключений во время выполнения.

Без изменений при использовании Integer.MAX_VALUE вместо "0x7fffffff"

Я пробовал это на некоторых java-компиляторах с 1.2 до 1.6, и он все еще показывает это поведение.Теперь мне интересно, почему это так?

  • Это ошибка или функция?
  • Это невозможно обнаружить или проблема с низким приоритетом для разработчиков компиляторов?
  • Не исправлено ли это из-за обратной совместимости?
  • Может быть, в более новых выпусках JDK можно ли управлять этим во время компиляции, включив некоторые редко используемые свойства ключа / /:: переключателя компилятора или некоторый аргумент виртуальной машины Java (-XX: ...)?

Только сейчас я использовал эти виртуальные машины, 32-битные Windows x86

Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)

и

Java(TM) SE Runtime Environment (build 1.7.0_03-b05)
Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode, sharing)


Кстати, C # (Microsoft.CSharp \v4.0_4.0.0.0) показывает то же поведение
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OverflowCheck
{
    class Overflow
    {
        static void Main(string[] args)
        {
            int big = 0x7fffffff; // same behaviour vor Int32.MaxValue
            prt("big = " + big);
            int bigger = big * 4;
            prt("bigger = " + bigger);
            prt("done");
        }
          static void prt(String s) {
            System.Console.WriteLine(s);

        }
    }
}

Вывод:

big = 2147483647
bigger = -4

Ответы [ 3 ]

4 голосов
/ 19 февраля 2012

Спецификация языка предписывает поведение циклического переноса для переполнения вычислений, так что это особенность.Поскольку большинство переполнений не могут быть обнаружены во время компиляции, имеет сомнительную ценность для проверки тех, которые могут быть обнаружены, в частности, потому что они могли быть преднамеренными.

2 голосов
/ 19 февраля 2012

Это указано в спецификации языка Java: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.2

Встроенные целочисленные операторы никоим образом не указывают на переполнение или потерю значения.

Такжепочти все языки будут вести себя таким образом, используя переполнение по кругу вместо выдачи ошибки переполнения.Зачем?Отчасти потому, что исторически так было, и потому что проще смотреть на целочисленную арифметику как на чисто бинарную операцию.

1 голос
/ 19 февраля 2012

Вероятно, это связано с проблемами производительности .

Для большого объема данных проверка правильности числового диапазона может привести к значительному замедлению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...