我知道这个问题已部分回答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编译器上试过这个,但它仍然显示了这种行为。我现在想知道为什么会这样?
刚才我使用了这些虚拟机,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
答案 0 :(得分:4)
语言规范要求溢出计算的环绕行为,因此它是一个特性。由于在编译时无法检测到大多数溢出,因此检查可检测到的溢出值是不确定的,特别是因为它们可能是故意的。
答案 1 :(得分:2)
这在java语言规范中指定:http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.2
内置整数运算符不以任何方式表示溢出或下溢。
此外,几乎所有语言都会通过使用环绕溢出而不是抛出溢出错误来表现。为什么?部分原因在于历史上它是这样的,并且因为如果将整数运算视为纯二进制运算,它会更容易。
答案 2 :(得分:1)
这可能是由于performance concerns。
对于大量数据,验证数值范围的正确性可能会导致显着减速。