不劳而获

Posted by Codeboy on November 6, 2014

下面的程序将打印一个单词,其首字母有一个随机生成器选择,请描述改程序的行为:

import java.util.Random;

public class Main {
    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.是这样吗?

聪明的您可能发现问题了, Random.nextInt(int n)的范围是在0-n之间,含0不含n,所以整体上Random.nextInt(2)只会产生0或者1,所以程序是不会打印出Gain的,应该是等概率的输出Main与Pain。(栅栏柱错误)

看起来似乎正确了,但是哪里还是有些问题。看到了,是switch循环后面没有加上break,这样的话,Random.nextInt(2)产生1时会将3个case语句全部执行,也即相当于执行default里的语句;Random.nextInt(2)产生0时也是执行default里的语句,这样下来最终的结果只能有一个,那就是Main了。(switch-case-break错误)

复制代码,运行一下,发现结果是ain,不管运行多少次,结果都是一样的,为什么没有打印出M呢,下面我们来看一下StringBuffer,StringBuffer类没有对应的字符构造函数,在eclipse中可以将鼠标放在case中的构造器中,提示了一下内容:

java.lang.StringBuffer.StringBuffer(int capacity)

	Constructs a string buffer with no characters in it and the specified initial capacity.

Parameters:
	capacity the initial capacity.
	Throws:
	NegativeArraySizeException - if the capacity argument is less than 0.

这下明白了,原来StringBuffer(‘M’)在构造的时候,是构造了一个容量为’M’对应ascii值大小的初始容量,之后再附加字符之前,都没有任何内容,所以最终的结果始终是Main。(非常规方法使用错误)

上面的3处错误或者问题是经常出现的,希望大家都能够多注意。

如有任何知识产权、版权问题或理论错误,还请指正。

转载请注明原作者及以上信息。