为什么Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

是真的。

我知道在Java中的整数是32位,不能超过2 ^ 31-1,但我不明白为什么加1到MAX_VALUE结果在MIN_VALUE而不是某种exception。 没有提到像透明转换到更大的types,就像Ruby一样。

这种行为指定的地方? 我可以依靠吗?

因为整数溢出。 当它溢出时,下一个值是Integer.MIN_VALUE 。 相关的JLS

如果整数加法溢出,那么结果是math和的低位,如用一些足够大的二进制补码格式表示的。 如果发生溢出,则结果的符号与两个操作数值的math和的符号不同。

整数存储溢出并且不以任何方式指示,如JSL第3版所述。 :

内置的整数运算符不会以任何方式指示上溢或下溢。 如果需要对空引用进行拆箱转换(第5.1.8节) ,则整型运算符可能会引发NullPointerException 。 除此之外,可以抛出exception(§11)的唯一整数运算符是整数除法运算符/ (第15.17.2节)和整数余数运算符% (第15.17.3节) ,如果右键点击时抛出ArithmeticException ,手操作数为零,递增和递减操作符++ ( §15.15.1 , §15.15.2 )和-- ( §15.14.3§§15.14.2 ),如果装箱转换可以抛出OutOfMemoryError (§5.1 .7)是必需的,没有足够的内存可用于执行转换。

4位存储示例:

 MAX_INT: 0111 (7) MIN_INT: 1000 (-8) 

MAX_INT + 1:

  0111+ 0001 ---- 1000 

我相信这个链接解释你所看到的: http : //en.wikipedia.org/wiki/Two's_complement

您必须了解整型值如何以二进制forms表示,以及二进制加法如何工作。 Java使用称为二进制补码的表示法,其中数字的第一位表示其符号。 无论何时将1添加到最大的具有位符号0的Java Integer,其位标记都将变为1,并且该数字变为负数。

这个链接解释了更多细节: http : //www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

Java语言规范在此处理此行为: http : //docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

如果整数加法溢出,那么结果是math和的低位,如用一些足够大的二进制补码格式表示的。 如果发生溢出,则结果的符号与两个操作数值的math和的符号不同。

这意味着你可以依靠这种行为。

当你越过国际date线时date发生变化的原因是一样的:那里有一个不连续点。 它build立在二进制加法的本质上。

这是一个众所周知的问题,整数在二进制层表示为二进制补码 。 当你给一个二进制补码的最大值加1时,你会得到最小值。 说实话,所有的整数都是在java存在之前以这种方式performance的,改变Java语言的这种行为会给整数math增加更多的开销,而来自其他语言的混淆程序员也会增加。

当你将3 (二进制11 )加到1(二进制1 )时,你必须从右边开始把二进制1变成0 (二进制0 ),直到你得到0,你应该改成1Integer.MAX_VALUE已经填满了1所以只剩下0秒。

在大多数处理器上,算术指令没有模式来处理溢出错误。 他们设置了一个必须检查的标志。 这是一个额外的指令,所以可能会更慢。 为了使语言实现尽可能快,语言经常被指定为忽略错误并继续。 对于Java,行为在JLS中指定。 对于C来说,语言并没有指定行为,但是现代处理器的行为就像Java一样。

我相信有一些build议(尴尬的)Java SE 8库引发溢出,以及未签名的操作。 我相信在DSP领域stream行的行为是将值限制在最大值,所以Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [不是Java]。

我敢肯定,未来的语言将使用任意精度整数,但暂时还没有。 需要更昂贵的编译器devise才能快速运行。