A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 Union 于 2014-4-28 23:24 编辑

下面的程序将打印一个单词,其第一个字母是由一个随机数生成器来选择的。该程序:
  1. import java.util.Random;
  2. public class Rhymes {
  3.     private static Random rnd = new Random();
  4.     public static void main(String[]args) {
  5.         StringBuffer word = null;
  6.         switch(rnd.nextInt(2)) {
  7.             case 1:  word = new StringBuffer('P');
  8.             case 2:  word = new StringBuffer('G');
  9.             default: word = new StringBuffer('M');
  10. }
  11. word.append('a');
  12. word.append('i');
  13. word.append('n');
  14. System.out.println(word);
  15.     }
  16. }
复制代码

乍一看,这个程序可能会在一次又一次的运行中,以相等的概率打印出 Pain,
Gain 或 Main。看起来该程序会根据随机数生成器所选取的值来选择单词的第一
个字母:0 选 M,1 选 P,2 选 G。谜题的题目也许已经给你提供了线索,它实际
上既不会打印 Pain, 也不会打印 Gain。 也许更令人吃惊的是,它也不会打印 Main,
并且它的行为不会在一次又一次的运行中发生变化,它总是在打印 ain。

这是为什么?


欢迎解答!



评分

参与人数 1技术分 +1 收起 理由
SyouRai_Tsk + 1

查看全部评分

9 个回复

倒序浏览
  1. /*
  2. import java.util.Random;
  3. public class Rhymes
  4. {
  5.     private static Random rnd = new Random();
  6.     public static void main(String[]args)
  7.         {
  8.         StringBuffer word = null;
  9.         switch(rnd.nextInt(2))//此处应是3,生成的随机数是0和指定值之间的数,不包括指定值
  10.                 {
  11.             case 1:  word = new StringBuffer('P'); //此处应传入字符串而不是字符,而且缺少break;否则只赋值最后一个
  12.             case 2:  word = new StringBuffer('G'); //至于为什么传入错误的数据类型可以成功创建对象,不太清楚
  13.             default: word = new StringBuffer('M');
  14.                 }
  15.                 word.append('a');
  16.                 word.append('i');
  17.                 word.append('n');
  18.                 System.out.println(word);
  19.     }
  20. }
  21. */

  22. //下面对原代码做了一下改善,结果是成功的

  23. import java.util.Random;
  24. public class Demo
  25. {
  26.         private static Random rnd = new Random();
  27.         public static void main(String[]args)
  28.         {
  29.                 for (int i=1;i<20;i++ )
  30.                 {
  31.                         StringBuffer word = null;
  32.                         switch(rnd.nextInt(3))
  33.                         {
  34.                                 case 0:  word = new StringBuffer("P"); break;
  35.                                 case 1:  word = new StringBuffer("G"); break;
  36.                                 default: word = new StringBuffer("M");
  37.                         }
  38.                         word.append('a');
  39.                         word.append('i');
  40.                         word.append('n');
  41.                         System.out.println(word);
  42.                 }
  43.         }
  44. }
复制代码
回复 使用道具 举报
学习了,小细节很重要
回复 使用道具 举报

对于给StringBuffer传入字符可以成功创建对象的原因知道了。
StringBuffer中有一个构造函数StringBuffer(int capacity),
用于构造一个不带字符,但具有指定初始容量的字符串缓冲区。
传入的char类型的字符,被自动转换成了int类型,用于指定字符串缓冲区的初始容量。
回复 使用道具 举报
查了下帮助文档,发现StringBuffe的构造函数有
[size=+2]构造方法摘要
StringBuffer()
          构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
StringBuffer(CharSequence seq)
          public java.lang.StringBuilder(CharSequence seq) 构造一个字符串缓冲区,它包含与指定的 CharSequence 相同的字符。
StringBuffer(int capacity)
          构造一个不带字符,但具有指定初始容量的字符串缓冲区。
StringBuffer(String str)
          构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容

并没有StringBuffer(char ch)类型的构造函数,所以在new StringBuffer('P')时,会把字符自动转换为int类型的。即调用StringBuffer(int capacity)。此构造函数作用是“构造一个不带字符,但具有指定初始容量的字符串缓冲区。”所以在switch循环后,word里面仍然没有字符。故会一直打印ain
还有一点,rnd.nextInt(2)只会出现0或1,故应该把case(2)换为case(1)。并在case子句里加上break关键字。在new对象的时候参数应该是字符串而不是字符。

回复 使用道具 举报
2L正解。
首先是随机数的问题,nextInt(n),会产生0至n-1的随机整数。例如nextInt(2),只会产生0,1这两个整数。
其次是new StringBuffer的问题。new String('P'),在StringBuffer的构造函数中,没有接受单个字符的构造方法。但是有一个int型的参数,用于指定底层StringBuilder缓冲区大小的,
所以程序中实际上创建的是一个指定了capacity大小的StringBuffer对象,没有具体的内容。
最后就是case穿透的问题了,在case中没有break,就会一直执行到末尾的default语句上。

回答的貌似有些晚了,就当是总结吧,嘿嘿。
回复 使用道具 举报
Union 高级黑马 2014-4-29 19:49:02
7#
谢振宣 发表于 2014-4-29 13:40
对于给StringBuffer传入字符可以成功创建对象的原因知道了。
StringBuffer中有一个构造函数StringBuffer( ...

回答的不错啊!
回复 使用道具 举报
Union 高级黑马 2014-4-29 19:50:06
8#
土突突 发表于 2014-4-29 14:49
查了下帮助文档,发现StringBuffe的构造函数有

回答的挺对的!
回复 使用道具 举报
  1. StringBuffer word = new StringBuffer('h');
  2.                 System.out.println('h'+0);
  3.                 System.out.println(word.capacity());
复制代码


如果你传入的字符而不是字符串的时候,那么你要知道StringBuffer有一个构造函数是StringBuffer(int capacity),那么Java会自动将字符‘h’转化为int型,在这里也就是104,所以你打印出来的总是ain。
回复 使用道具 举报
嘿嘿,这个程序有点意思啊,考验小细节,学习了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马