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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 火之意志 中级黑马   /  2013-5-22 23:15  /  1660 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 火之意志 于 2013-5-23 13:21 编辑

StringBuffer buffer=new StringBuffer();
        buffer.append("HelloWorld!");
        buffer.insert(5,buffer);
        System.out.println(buffer);

        结果为什么会是:HelloHelloHelloHe World!而不是HelloHello World World! ?
ps:通过试验,只要不是buffer对象,其他类型的对象都可以用insert方法插入

评分

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

查看全部评分

12 个回复

倒序浏览
这个不知道 盲点 看别人回答
回复 使用道具 举报
因为当你在(5,buffer)这个位置插入的时候 buffer是改变的,所有会不断的在第五个位置插入
回复 使用道具 举报
楼上说的貌似靠谱,,,,但是具体的插入过程呢?????
回复 使用道具 举报
同求具体过程
回复 使用道具 举报
因为buffer是同一个区域。一旦,这个区域添加了一个元素,那么,整个区域就是变化的。
        结果就不可预料
回复 使用道具 举报
1、通过断点调试,发现buffer.insert(5,buffer) 这个方法的插入逻辑如下图
   
2,关键点在于buffer1.insert(5,buffer2)是取一个字符再插入一个字符,当buffer1和buffer2不一样,这个自然不会有问题。
当buffer1==buffer2,后面取的字符可能是前面刚插入进去的,而不是原始需要插入的字符。
它只记字符索引值,这样就会出错。
3、看来源码里面还是有bug的。。。应该先把buffer2的字符放到temp里面,谁能想到,经过这么长的迭代,
会有value==s?关键位置源码
for (int i=start; i<end; i++)
            value[dstOffset++] = s.charAt(i);
//AbstractStringBuilder的1115-1116行。
   
回复 使用道具 举报
这里,源和目的都是StringBuffer的实例对象buffer,在插入元素的过程中,buffer在不断变化,也就是说源和目的在不断地变化,变化的过程如下。
调用insert之前,buffer的值为“HelloWorld!”,insert调用过程就是将源转换成字符数组,然后将字符数组中的每一个元素插入到目的中,步骤如下:


注意,数据源和数据目的都在变化

1. 将数据源HelloWorld!的第1位置元素H插入到buffer的第5个位置(下标从0开始,下面相同,buffer的值变成HelloHWorld!;
2. 将数据源HelloHWorld!的第2
位置元素e插入到buffer的第6个位置,buffer的值变成HelloHeWorld!;
3. 将数据源HelloHeWorld!的第3
位置元素l插入到buffer的第7个位置,buffer的值变成HelloHelWorld!;
4. 将数据源
HelloHelWorld!的第4位置元素l插入到buffer的第8个位置,buffer的值变成HelloHellWorld!;
5. 将数据源
HelloHellWorld!的第5位置元素o插入到buffer的第9个位置,buffer的值变成HelloHelloWorld!;

注意,下面开始有变化了,这种变化是因为数据源和数据目都是同一个StringBuffer对象的引用buffer造成的

6. 将数据源HelloHelloWorld!的第6位置元素H插入到buffer的第10个位置,buffer的值变成HelloHelloHWorld!;
7. 将数据源HelloHelloHWorld!的第7位置元素e插入到buffer的第11个位置,buffer的值变成HelloHelloHeWorld!;
8. 将数据源HelloHelloHeWorld!的第8位置元素l插入到buffer的第12个位置,buffer的值变成HelloHelloHelWorld!;
9. 将数据源HelloHelloHelWorld!的第9位置元素l插入到buffer的第13个位置,buffer的值变成HelloHelloHellWorld!;
10. 将数据源HelloHelloHellWorld!的第10位置元素o插入到buffer的第14个位置,buffer的值变成HelloHelloHelloWorld!;
11. 将数据源HelloHelloHelloWorld!的第11位置元素H插入到buffer的第15个位置,buffer的值变成HelloHelloHelloHWorld!;

之所以执行11次将字符数组中的元素插入到buffer中,是因为原来的buffer的值“HelloWorld!”长度为11。


回复 使用道具 举报
本帖最后由 无妄无涯 于 2013-5-23 12:09 编辑

由你的结果得出字符串应该是“Hello World”,即中间有空格。源字符串和目的字符串都是buffer,根据你的方式,buffer中的内容在不断变化。由于要加入的字符串“Hello World!”长12,因此在执行插入时会给buffer增加12字节的长度,然后从索引5处开始插入,直到24字节长度占满。过程是这样:


如果想完成要求的效果可以这样:
  1. class Test {
  2.         public static void main(String[] args) {
  3.                
  4.                 StringBuffer buffer=new StringBuffer();
  5.                 StringBuffer buffer1=new StringBuffer();
  6.         buffer.append("HelloWorld!");
  7.         buffer1.append("Hello World!");
  8.         buffer.insert(5,buffer1);
  9.         System.out.println(buffer);
  10.         }
  11. }
复制代码
回复 使用道具 举报
这个bug太吓人了。。。
为什么不这样做呢?
buffer.(5,buffer.toString);
回复 使用道具 举报
这个题目确实有意思:
但是如果说如果源代码中使用final关键字就不会出现这种问题了
从设计思想上说,即封装性;
你给我传递的参数是不允许改变的;
回复 使用道具 举报
恩,大神们说的有道理,我自己也试验了,只要不是StringBuffer的对象,调用insert()方法都可以通过,唯独不能自己插入自己,既buffer。insert(3,buffer)是错误的,其他类型的对象都可以
回复 使用道具 举报
设置一断点,跟着程序走,就可以知道inser()方法里面是怎么插入的。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马