如果你没有看过Java解惑这本书的话呢?我敢说下面的这些循环会把你彻底的搞蒙,因为他们实在是太贱了,贱的你想揍他,但是他面对着,微笑依然......
哈哈,废话不多说,下面我们来进入正题.....
话说,循环大家都不陌生,for循环,while循环,do ...while 循环我们都如数家珍。但是这里面有很多比较特殊的情况,下面一一来揭开他们神秘的面纱。
第一个例子:
public static final int END=Integer.MAX_VALUE; public static final int START=END-100; public static void main(String[] args){ int count=0; for(int i=START;i<END;i++){ count++; } System.out.println(count); }
这个程序结果为:100
下面我做下小小的手脚,如下:
public static final int END=Integer.MAX_VALUE; public static final int START=END-100; public static void main(String[] args){ int count=0; for(int i=START;i<=END;i++){
//注意此处由<改为<=
count++; } System.out.println(count); }
这个程序会打印什么结果呢?是101还是其他的呢?
运行之后你会发现,这个程序什么都没有打印,这是为什么呢?
Integer.MAX_VALUE是int类型最大的数值,当i=Integer.MAX_VALUE,然后i++,他就又绕回到了Integer.MIN_VALUE。如果需要的循环会迭代到int数值的边界附近,最好是使用一个long变量作为循环索引。即将for循环改为:for(long i=START;i<=END;i++) 这样打印结果就是101.或者做如下修改:int i=START;do{count++;}while(i++!=END);
第二个例子:
定义start 使得for(int i=start;i<start+1;i++)是一个死循环,有第一个例子我们很简单的就知道 int start =Integer.MAX_VALUE-1;
第三个例子:
如何使得下面这个循环变成一个无限循环while(i==i+1){}
我们知道无穷大加1还是无穷大,所以我们在循环之前将i初始化一个无穷大的值,那么终止条件i=i+1就会永远计算为true,我们可以定义为double i=0.0/0.0;不过最好使用标准类库提供的常量。double i=Double.POSITIVE_INFINITY; 事实上,不必将i初始化为无穷大以确保循环永远执行,任何足够大的浮点数都可以实现这一目的,例如:
double i=1.0e40;
第四个例子:
提供一个对i的声明,将下面这个循环转变为无限循环
while(i!=i){}
我们大家一致的印象都是:一个数字总是和他自己是相等的,怎么会是死循环呢?但是在浮点数中有一个特例那就是NaN不等于任何浮点数值,包括他自己本身。所以我们可以这么来定义 double i=0.0/0.0;同样为了表达清晰,我们还是使用标准类库提供的常量:double i=Double.NaN;
第五个例子:
提供一个对i的声明,将下面这个循环转变为无限循环
while(i!=i+0){}
看到这个的时候,你是不是有点晕了,我们知道不能将i声明为浮点数,我们知道在整数中没有NaN这个特例,不由的我们会想,i一个是一个非数值类型的数据,唯一的+操作符有定义的非数值类型的就是String。+操作被重载了,对于String类型执行+操作不是加法,而是字符串的连接。所以我们只要将i声明为一个字符串,那么将实现这个例子。即: String i=“hello world”;
第六子例子:
提供一个对i的声明,将下面的循环转变为一个无线循环:
while(i!=0){i>>>=1;} 我们知道>>>=是一个符合运算符。窄化原生类型转换可能会丢失级数的信息,或者是数值的精度。
假设我们声明 short i=-1;初始化为非0(0xffff);再循环移位的时候将i提升为int类型,所产生int数值为0Xffffffff,然后右移一位变为0x7fffffff,将int型转化为short型,进行窄化处理之后还是0xffff。所以不管如何,每次循环都会回到原点。
将i声明为short和byte都是可以的,但是不能声明为char 以为char是无符号的。
总之,不要在short和byte和char的变量上使用复合赋值操作符。
第七个例子:
声明i,j是下面循环转换为无限循环;
while(i<=j&&i>=j&&i!=j){}
这个看似会简单些,我们只要将i,j声明为不同的整型对象就ok ,例如:
Integer i=new Integer(0);
Integer j=new Integer(0);就可以达到上面我们要的效果。
第八个例子:
声明i是下面循环转换为无限循环;
while(i!=0&&i==-i){}
我们知道有符号的整数类型使用2的补码进行算法运算。
Integer.MIN_VALUE,他的十六进制表示为:0x80000000,其符号位为1,其余全部为0.如果对于这个值取负值,将得到0x7fffffff+1,也就是0x80000000.也就是说
Integer.MIN_VALUE就是他自己的复数。
因此我们定义int i=Integer.MIN_VALUE;或者long i=Long.MIN_VALUE 都可以达到目的!
看来上面的八个例子,相信大家对这个黑色的循环会有更深的了解。