《Java解惑》书摘
例子1:关于char数组的输出
1 System.out.println("H" + "a");//输出:Ha 2 System.out.println(‘H‘ + ‘a‘);//输出:169 3 System.out.println("" + ‘H‘ + ‘a‘);//输出:Ha 4 System.out.println("//////////////////"); 5 System.out.println("2 + 2 = " + 2 + 2);//输出:2 + 2 = 22 6 System.out.println("2 + 2 = " + (2 + 2));//输出:2 + 2 = 4 7 System.out.println("//////////////////"); 8 char[] char1 = {‘1‘, ‘2‘, ‘3‘}; 9 Object char2 = new char[] {‘1‘, ‘2‘, ‘3‘}; 10 System.out.println(char1);//输出:123 11 System.out.println(char2);//输出:[C@55e83f9 12 System.out.println("test-" + char1);//输出:test-[C@55e83f9 13 System.out.println("test-" + char1.toString());//输出:test-[C@55e83f9 14 System.out.println("test-" + String.valueOf(char1));//输出:test-123 15 System.out.println("//////////////////");
例子2:
1 Random random = new Random(); 2 StringBuffer sBuffer = null; 3 switch(random.nextInt(2)) { 4 case 1:sBuffer = new StringBuffer(‘A‘); 5 case 2:sBuffer = new StringBuffer(‘B‘); 6 default:sBuffer = new StringBuffer(‘C‘); 7 } 8 sBuffer.append(‘a‘); 9 sBuffer.append(‘b‘); 10 sBuffer.append(‘c‘); 11 System.out.println(sBuffer);//输出:abc 12 }
这段程序有三个BUG:
- Random.nextInt(int n)方法的使用错误:
先看下这个方法的API:
public int nextInt(int n)
返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
所以,此处应改为:switch(random.nextInt(3)) { - case子句中没有break语句:
导致前面的赋值被后面的赋值覆盖。 - StringBuffer类的构造方法使用错误:
StringBuffer不支持传入参数为字符(char)的构造方法,应改为传入字符串(String),
所以,应改为:sBuffer = new StringBuffer("A");
例子3:会死循环的代码
1 //死循环1 2 int start1 = Integer.MAX_VALUE-1; 3 for(int start7=start1; start7<=start1+1; start7++) { 4 System.out.println("loop.."); 5 } 6 //死循环2 7 double start2 = 1.0 / 0.0; 8 double start3 = Double.POSITIVE_INFINITY;//与上句等价,可替代 9 while(start2 == (start2+1)) { 10 System.out.println("loop.."); 11 } 12 //死循环3 13 double start4 = 0.0 / 0.0; 14 double start5 = Double.NaN;//与上句等价,可替代 15 while(start4 != start4) { 16 System.out.println("loop.."); 17 } 18 //死循环4 19 String start6 = "test"; 20 while(start6 != (start6+0)) { 21 System.out.println("loop.."); 22 } 23 //死循环5 24 byte start7 = -1;//死循环 25 // short start7 = -1;//死循环 26 // int start7 = -1;//循环32次 27 // long start7 = -1;//循环64次 28 int count = 0;//循环次数 29 while(start7 != 0) { 30 start7 >>>= 1; 31 System.out.println("loop.."); 32 count++; 33 } 34 System.out.println("循环次数 = " + count); 35 //死循环6 36 int start8 = Integer.MIN_VALUE; 37 // Long start8 = Long.MIN_VALUE; 38 while(start8 != 0 && start8 == -start8) { 39 System.out.println("loop.."); 40 }
补充说明:
- 关于Infinity和NaN(死循环2和3)
1 double d = 1.0 / 0; 2 System.out.println(d); //输出:Infinity 3 System.out.println(d + 1); //输出:Infinity 4 System.out.println(d == d + 1); //输出:true 5 6 d = 0.0 / 0; 7 System.out.println(d); //输出:NaN 8 System.out.println(d + 1); //输出:NaN 9 System.out.println(d == d + 1); //输出:false 10 11 System.out.println(Double.NaN == Double.NaN);//输出:false 12 Double a = new Double(Double.NaN); 13 Double b = new Double(Double.NaN); 14 System.out.println(a.equals(b));//输出:true
- 关于Java的自动窄化原生类型转换(死循环5)
分析 short start7 = -1; 和 start7 >>>= 1;这两句代码:
在执行移位操作时,第一步是将start7提升为start7nt类型,因为所有的算术操作都会对short,byte,char类型的操作数执行这样的提升;
这种提升是拓宽了原生类型,没有信息的损失,执行的是符号扩展,start7的值提升后是0xffffffff,start7>>>1之后得到的是0x7fffffff;
将这个值再存入start7中的时候,为了将int数值存入short变量,Java自动执行了可怕的窄化原生类型,直接把高16位截掉,剩下(short)0xffff,又回到了起点,从而导致了死循环。
这提醒了我们,不要在short,byte,char类型上使用复合赋值操作符,很容易出问题,而且这种隐性的窄化类型转换,在丢失信息的同时,结果也可能是灾难性的。 - 关于Java中的特殊值(死循环6)
Java使用2的补码的算术运算是不对称的。
对于每一种有符号的整数类型(byte、short、int和long),负的数值总是比正的数值多一个,这个多出来的数值总是这个类型所能表示的最小值;
对Integer.MIN_VALUE取负值并不会改变它的值,对这个值取负值将会产生溢出,但是Java自动忽略了这种溢出;同理对Long.MIN_VALUE等也是如此。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。