循环之谜总结

1.类型转换时的问题

问题:byte b = (byte)0x90;等于多少?    -112

分析:

(1)int占32位,byte占8位

(2)而0x90看上去可以用8位表示,但是byte因为是有符号数,因此范围是-128~127,而0x90是144,如果用byte表示的话,由于最高位被置位,因此是-112.

总结:

避免混合类型的比较或赋值。

public class PuzzlerDemo24{
	public static void main(String args[]){
		byte by = (byte)0x90;
		System.out.println(by);
		for(byte b=Byte.MIN_VALUE;b<Byte.MAX_VALUE;b++){
			if(b == (byte)0x90){
				System.out.println("Joy!"); 
			}
		}
	}
}


2.增量操作的困惑

问题:int j = j++;j等于多少?    原值

分析:

(1)j++的执行过程:j的值加一,但返回原始值。

(2)j = j++的过程:

     int tmp = j;

     j = j+1;

     j = tmp;

因此j还是原来的值。

总结:

不要在一个表达式中对同一个变量赋值多次。

public class PuzzleDemo25{
	public static void main(String args[]){
		int j = 0;
		for(int i=0;i<100;i++){
			j++;
		}
		System.out.println(j); 
	}
}


3.int的讨论

(1)int的取值范围:-231~231-1,因此取值范围是不对称的。

(2)Integer.MAX_VALUE:int中的最大值,如果Integer.MAX_VALUE+1则等于Integer.MIN_VALUE;因此不可能会有整数超过此值。

(3)Integer.MIN_VALUE:int中的最小值,他的负数还是原来的值,不变。

(4)int是有边界的,不像Float不存在边界。

特性:

(1)Integer.MAX_VALUE+1==Integer.MIN_VALUE;

(2)如果一个数值会在Integer的边界附近,则最好使用long值。

(3)对于有符号的整数类型,负的数值总比正的数值多一个。

public class PuzzleDemo26{
	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); 
	}
}


4.浮点数的讨论

问题:

double i =Double.POSITIVE_INFINITY;

i==i+1返回的是true还是false?

分析:

(1)大的浮点数与其后继之间是有间隔的,这个间隔可能很大,无穷大与后继的间隔是无穷大。

(2)对于一个足够大的浮点数加上1后并不会改变他的值,因为1不能弥补两个浮点数之间的空隙。

(3)ulp(Unit in the last place):两个浮点数之间的空隙。java.lang.Math.ulp(double d)可以计算出d的ulp是多少.

总结:

(1)二进制浮点算术只是对实际算术的一种近似。

(2)一个很小的浮点数加到很大的浮点数上时,可能不会改变大浮点数的值。

浮点数特点:

1.利用浮点数可以表示无穷大,无穷小。POSITIVE_INFINITYNEGATIVE_INFINITY

2.Double.NaN:不是一个数,因此他与任何数值比较都不相等,包括他自己

public class PuzzleDemo28{
	public static void main(String args[]){
		double d = Double.POSITIVE_INFINITY;
		System.out.println("无穷大的浮点数值间隔是:" + Math.ulp(d)); 
		System.out.println("d与d+1是否相等:" + (d==d+1)); 
	}
}

public class PuzzleDemo29{
	public static void main(String args[]){
		double i = Double.NaN;
		while(i!=i){
			System.out.println("继续执行!"); 
		}
		System.out.println("停止!"); 
	}
}


5.移位操作符的讨论

一、问题:-1<<32为多少?    -1

分析:

(1)-1是int值,所以有32位。

(2)当左操作数是int类型,则截取右操作数的5位,即右操作数一定要小于32;当左操作数是long类型,则截取右操作数的6位,即右操作数一定要小于64.

(3)如果上述例子的右操作数为32,则左操作数不变。

(4)如果上述例子的右操作数超过32,则需要对右操作数取余。

二、问题:-1<<-1为多少?  -1<<31

结论:

(1)右移操作符总是起到右移的作用,而左移操作符总是起到左移的作用。

(2)负的移位长度通过只保留低5位使得变成正的移位长度。

(3)使用移位操作符,不可能一次性的把一个数值的全部位移走!

public class PuzzleDemo27{
	public static void main(String args[]){
		System.out.println("-1>>32:" + (-1>>32)); 
		System.out.println("-1>>>-1:" + (-1>>>-1));	//注意逻辑右移和算术右移的区别
		System.out.println("-1>>-1:" + (-1>>-1)); 
		
	}
}
/*
-1>>32:-1
-1>>>-1:1
-1>>-1:-1
*/

6.不可能的事实

问题:有没有可能i<=j&&i>=j&&i!=j返回true? i = new Integer(0),j = new Integer(0)

分析:

(1)数值类型肯定是不行的。

(2)i!=j:如果i,j是基本数据类型,则表示值比较,而如果是引用数据类型,则表示对象引用比较。

(3)jdk5.0中新增了自动打包和拆包功能.

结论:

当两个操作数都是被包装的数字类型,则数值比较操作符执行的是值比较,而判等操作符执行的是引用标识比较。

7.“+”的重载

问题:i==i+0吗? 不一定

分析:

(1)对于String类型,+表示连接,因此如果i是一个String,则表示字符串连接。

结论:

”+“操作符有两个作用:

(1)数值计算。

(2)字符串连接。

public class PuzzleDemo30{
	public static void main(String args[]){
		String i = "a";
		while(i!=i+0){
			System.out.println("执行!");
		}
		System.out.println("停止!"); 
	}
}


8.复合操作符的再次来袭

问题:i>>>=1后i的值可能不变吗? 可能。

分析:

(1)>>>=解析:a>>>=b 等价于  a=(TypeA)(a>>>b);

(2)举例:

short i = -1     i =  0xffff; 

int j = i;           j = 0xffffffff;

j>>>=1;          j = 0x7fffffff;

i = (short)j;     i = 0xffff;        不变。

public class PuzzleDemo31{
	public static void main(String args[]){
		short i = -1;
		while(i!=0){
			i>>>=1;
		}
		System.out.println("停止!"); 
	}
}


9.包装类的比较操作符和判等操作符(==或!=)

对于判等操作符

(1)对于基本类型,则表示值比较。

(2)对于引用数据类型,则表示对象引用比较,包括Integer等包装类。

总结:

当两个操作数都是被包装的数字类型时,数值比较操作符是执行的值比较,而判等操作符执行的是引用标识比较。

如果有一个是被包装的数字类型,而另一个是基本类型,则判等操作符执行的是值比较。

public class PuzzleDemo32{
	public static void main(String args[]){
		Integer i = new Integer(1);
		Integer j = new Integer(1);
		while(i<=j && i>=j && i!=j){}
		System.out.println("停止!"); 
	}
}


10.会发生精度丢失的三种拓宽基本类型转换

(1)int-->float:

(2)long-->float:

(3)long-->double:

public class PuzzleDemo34{
	public static void main(String args[]){
		final int START = 2000000000;
		System.out.println(Math.ulp((float)START)); 
		int count = 0;
		for(float f=START;f<START+50;f++){
			count++;
		}
		System.out.println(count); 
	}
}


10.小心魔数!

魔数的定义:在一些程序代码中,程序员常常将在代码中出现但没有解释的数字常量或字符串称为魔数 (magic number)或魔字符串。

建议:用恰当命名的常量代替所有的魔数。

 

 

 

 

你可能感兴趣的:(循环之谜总结)