一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
运算溢出这个问题在 Java 面试中时长被问到,但是面试官不会直接问你运算溢出,而是通过编程题的形式进行考察,我们先来看一下面这道面试题:
请写出下面这段代码的输出结果
public static void main(String[] args){
int x = -2000000000;
int y = 2000000000;
System.out.println(x - y);
}
这段代码很多开发人员会简单的认为这段代码最后输出的结果是 -4000000000,但是这段代码运行起来后最终的输出是 294967296,这是为什么呢?这是因为 int 有范围限制,int 的最大值是2的31次方减1也就是 2147483647,最小值是-2的31次方也就是 -2147483648,很显然 -4000000000 已经超出了 int 的范围产生了溢出。那么这个溢出的值是如何计算出的呢?我们先来看一下 int 类型的源代码,其中有这么一段代码:
/**
* A constant holding the maximum value an {@code int} can
* have, 2<sup>31</sup>-1.
*/
@Native public static final int MAX_VALUE = 0x7fffffff;
在这段代码中以16进制的方式表示了 int 类型的最大值294967296,那么也就是说在执行运算的时候Java会将运算符左右两边的值转换为16进制,然后再进行计算并以16进制的形式输出就可以得到这个溢出的值。那么我们就按照这个思路来手动实现一下。
int x = -2000000000;
int y = 2000000000;
System.out.println(Integer.toHexString(x-z));
上面的代码中-2000000000的16进制数值为:0x88ca6c00,2000000000的16进制数值为:0x77359400,两个16进制数相减得到的值为0x1194d800,转换为十进制就是294967296。 这里只是用 int 来举了个例子,在 Java 中像 byte、short、long、char 只要运算的结果超过了其所能表示的而范围都会产生运算溢出的问题。