Arith在java中溢出:为什么在运行时没有异常且没有编译器警告?

时间:2012-02-19 10:45:40

标签: c# java overflow compiler-warnings

我知道这个问题已部分回答here on S.O.,但他们在那里解释在算术溢出期间发生了什么。在S.O.的其他地方他们在java代码中解释how to check for overflow,即防止它作为程序员。

这里我要求为什么在运行时没有异常,没有编译器警告

AFAIK,之前没有得到回答。

在Bruce Eckel的书Thinking in Java中,第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"

时无变化

我在1.2到1.6的一些java编译器上试过这个,但它仍然显示了这种行为。我现在想知道为什么会这样?

  • 这是一个错误或功能吗?
  • 这是不可能检测到的,还是编译器设计者的低优先级问题?
  • 由于向后兼容,这不是固定的吗?
  • 也许在较新版本的JDK中,可以通过启用一些很少使用的编译器开关/ -D:属性或某些java VM参数(-XX:...)来控制它吗?

刚才我使用了这些虚拟机,Windows x86 32位

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 个答案:

答案 0 :(得分:4)

语言规范要求溢出计算的环绕行为,因此它是一个特性。由于在编译时无法检测到大多数溢出,因此检查可检测到的溢出值是不确定的,特别是因为它们可能是故意的。

答案 1 :(得分:2)

这在java语言规范中指定:http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.2

  

内置整数运算符不以任何方式表示溢出或下溢。

此外,几乎所有语言都会通过使用环绕溢出而不是抛出溢出错误来表现。为什么?部分原因在于历史上它是这样的,并且因为如果将整数运算视为纯二进制运算,它会更容易。

答案 2 :(得分:1)

这可能是由于performance concerns

对于大量数据,验证数值范围的正确性可能会导致显着减速。