背景引入
今天老师上课的时候,写了一个循环语句,看起来就是普通的循环,不信看代码:
int count = 0;
while(true)
{
count ++;
if (count<20)
{
System.out.println("hello world");
}
}
小伙伴们,你们不妨先推测一下,如果运行,控制台的输出情况是怎样的。再去真正的运行一下,看你的推测是不是对的,然后再回来接着看。
和大部分人的第一想法一样(包括我),这段代码的初衷是为了在控制台打印20遍hello world。但事实上程序的运行情况是:像死循环一样在控制台不停的打印hello world。当时我人都傻了,我有一点java基础,对于这种简单的循环,理解起来应该不难才对,但是想了半天都想不明白是怎么回事。虽然while循环一直没有结束,但是当count增加到20之后,就不满足if的条件了呀,打印20次之后,就应该不会再打印了,为什么还会一直打印呢?
有大佬能一眼看出程序的运行结果,并且说出原因吗?
谜底揭晓
其实这段代码的运行,前面部分我们都是分析得没错的,问题就出在后面,当count增加到20之后,后面的执行情况。
一开始,打印了20遍之后,由于while是一个死循环,所以还会继续执行,count也会一直自增,直到数值达到int的最大值2^31 -1,也就是2147483647,由于java内部的处理机制,count就会变成 - 2 ^31,也就是-2147483648。这时候,count又小于20了,所以又会一直打印,这个负数会一直自增,到-1,到0,直到20,又会停止打印,然后到又重新变成一个负数,又开始打印。因为while是一个死循环,所以会如此的一直往复循环,为了直观,我画了个图:
当count处在黄线所表示的数值范围内时,就会打印hello world,在其他数值区间时,就不会打印。但是由于现在的计算机性能都非常的高,从20自增到21亿,也就是秒秒间的事情,所以我们的感觉就是:先打印了20遍,然后停顿一下,或者可能停顿都感觉不到,就开始不停的打印。
最终结论
int类型,4个字节,32位,但取值范围为什么是-2^ 31到2^ 31-1呢?是因为有一位符号位的存在,。int超过正向的范围之后,之所以会变成负数,就是因为,正数的符号位,也就是最高位是0,当正数超过最大值时,再向前进一位,最高位由0变成了1,所以就由正数变成负数。
//int c = Integer.MAX_VALUE+1//怕有的小伙伴看不懂
int c = 2147483647+1;
System.out.println(c);//-2147483648
另外,为啥int类型,不是-2147483647到2147483647呢,而是-2147483648到2147483647呢?这是因为。当1000 0000 0000 0000 0000 0000 0000 0000 代表-0,而0000 0000 0000 0000 0000 0000 0000 0000代表0,但是又不可能出现两个0。就强制规定1000 0000 0000 0000 0000 0000 0000 0000代表-2147483648,所以最小值就是-2147483648
有什么不对或不懂的地方,欢迎一起交流学习。
补充
没想到有一天还能再补充这篇博客,哈哈。前几天在找工作时,做在线试题的时候,做到了一个类似的题目:
我当就把桌子一拍,这题没有正确答案,然后义正言辞的给他们hr说:这题有问题!!!!!