大家一起找错误!(有趣的一道题,小心陷阱)
给出大家一段代码
import java.util.Random;
public class Rhymes {
private static Random rnd = new Random();
public static void main(String[] args) {
StringBuffer word = null ;
switch(rnd.nextInt(2))
{
case 1:word = new StringBuffer('P');
case 2:word = new StringBuffer('G');
default: word = new StringBuffer('M');
}
word.append('a');
word.append('i');
word.append('n');
System.out.println(word);
}
}
不知道大家认为这段代码最后输出的结果是什么?
是不是会认为会这个程序在运行中医相等的概率打印Pain,Gain,Main 呢?
如果你这么人认为那么恭喜你! 这段代码的里面包含的错误你一个没有发现!
如果你认为这个程序只会在Pain,Gain中等概率出现。
那么恭喜你,你发现了一个bug!
那即是:所选择的随机数只能使switch语句到达两种情况。Random.nextInt(int)的规范:”返回一个伪随机的,均匀分布在从0(包含)到指定的数值(不包含的)之间的任意一个数值”.
如果你认为最后结果只会是Main,那么强悍如斯的你,终于发现了第二个小bug.
没错!switch 语句中没有加break;那就表示不管哪种情况,最后执行的都是default语句且最后执行的default会把前面执行的覆盖掉。所以你会认为最后会只输出Main.
不过走到这一步,还是很遗憾的说一句,最后运行的结果不是这样!你还有一个小bug没有揪出来。那么究竟是什么bug呢?
通过查询API我们会发现.
根本就不存在StringBuffer(char)这样的构造器。
StringBuffer有一个无参构造器,一个接受一个String作为字符串缓冲区的构造器,一个接受一个int类型的构造器。
在本例中,编译器会选择接受int的构造器,通过拓宽基本类型转换把字符数值’M’转换为int的数值77!
所以一切就已经一目了然了。New StringBuffer(‘M’ 返回的是一个具有初始容量77的空字符缓冲区。该程序余下的部分将字符a,i和n添加到了这个空字符串缓冲区中,并且会打印其值,所以最后的结果总是ain.
改进之后的代码:
import java.util.Random;
public class Rhymes {
private static Random rnd = new Random();
public static void main(String[] args) {
StringBuffer word = null ;
switch(rnd.nextInt(2))
{
case 1:
word = new StringBuffer(“P”);
break;
case 2:
word = new StringBuffer(“G”);
break;
default:
word = new StringBuffer(“M”);
break;
}
word.append(“a”);
word.append(“i”);
word.append(“n”);
System.out.println(word);
}
}