不劳而获

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处错误或者问题是经常出现的,希望大家都能够多注意。

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

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

不劳而获