您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页正确区分String和StringBuffer

正确区分String和StringBuffer

来源:华佗小知识
正确区分String和StringBuffer

2

《Java改错学》本书作者虚构一个教学场景,采用一老一少的对话形式,将自己多年教学经验融入其中,传统教学模式,创新一种改错学Java的方法,帮助学习者树立正确的学习观念,使初学者明白,改错也是一种学习方式,在改正错误的过程中也能够学到和巩固很多基础知识,只要有了足够的基础,就可以编写出非常复杂和漂亮的程序。本节为大家介绍正确区分String和StringBuffer。

8 正确区分String和StringBuffer

一休:愚公,前面您说过要把String这个类搞懂,我碰到下面这个程序时,很认真地阅读它,并且去编译、运行了。这次我很仔细,一点也没有输入错。

1. public class StringTester

2. { public static void changeStrings(String s, StringBuffer sb) 3. { s+=\"by Definition\";

4. sb.append(\" by Definition\"); 5. }

6. public static void main(String args[]) 7. { String string=new String(\"Java\");

8. StringBuffer buffer=new StringBuffer(\"Java\"); 9. changeStrings(string, buffer);

10. System.out.println(\"String after method call:\"+string);

11. System.out.println(\"StringBuffer after method call:\"+buffer); 12. } 13. }

但不知道是没有读懂,还是程序存在问题,又要请教您了。

愚公:让我看看。这个例子很好,程序没有错,但这里有两个概念要搞清楚:

String类的对象是不可变的,即我们不可能改变String对象的值,而StringBuffer类的对象的值是可以改变的。

当引用变量作为方法的输入参数时,它的值同基本类型的变量一样可以被复制。如果在方法中试图改变引用变量的值,则这种改变是不可见的,但是它如果改变的是引用变量所指向的数据的值,那么这种改变就是可见的。

一休:还是不清楚,讲解太抽象了。

愚公:那我们就来读一读这个程序,并使用前面讲过的调试方法查看程序中变量的取值吧!

这是一个包含两个方法的程序,方法一是标准的main方法,方法二是changeStrings方法。main方法初始化两个对象,一个是String型,另一个是StringBuffer型,它们将作为changeStrings方法的输入参数,该方法将一个字符串连接在两个字符串变量的后面,然后利用两个println语句查看该改变在main方法中是否可见。

一休:我还是利用前面的方法把涉及到的对象、方法以及参数的传递画下来吧,如图9所示。

在画的过程中我发现一个问题:不是说String对象是不可变的吗,那么下面这个语句怎么解释呢?

1. s += \" by Definition\";

这个语句不是将s原来的字符串再加上\"by Definition\"后又赋给s吗?

愚公:这里看似是要改变String对象的值,但是实际上是创建一个新的字符串赋给它,而原来的对象丝毫没有改变。

在这段代码中,s原指向一个String对象,内容是\"Java\",然后我们对s进行了\"+\"操作。这时,s不指向原来的对象了,而指向了另一个String对象,内容为\"Java by definition\",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。

可以看出,changeString方法的作用是:利用\"+\"操作符把String类型变量与字符串\"by Definiton\"字符串拼接起来;使用append方法将StringBuffer类型的变量与字符串\"by Definiton\"字符串拼接起来。

一休:这两个拼接过程一样吗?

愚公:当然不一样,一个是要产生新的String类型字符串,另一个是在原来的基础上直接在后面拼接。一休,你可以把这个过程的结果画出来。

一休:好的,我来画。图10是我画的结果,对吗?

愚公:对的。但你执行一下看看。

一休:好的,程序执行后的输出如下。

1. C:\\>java StringTester

2. String after method call: Java

3. StringBuffer after method call: Java by Definition

噢,s对象没有改变。

愚公:我来解释一下吧。

在方法changeString中,字符串\"by Definition\"和s所指向的字符串拼接起来后产生一个新的字符串,其值为\"Java by Definition\"。于是变量s指向一新数据,这是由String类的性质决定的,即若要改变一个String对象的值,就需要创建一个新的字符串赋给它,但是这种改变只是发生在方法内部,在方法外不可见,这是由\"值传递\"的性质决定的。

另外,变量sb使用append方法修改了所指向数据的内容,\"by Definition\"被加入其后,但是sb这个引用(指针)本身的值并未发生改变,因为sb和buffer仍然指向原来的地址,而它们指向对象的值的改变是方法外可见的。

我也画了一张图给你看看。图11显示了一个引用类型变量作为方法参数时,实际引用类型的变量和方法的参数都是指向同一个对象。

一休:通过这个例子,可以看出利用一个引用变量作为方法的参数时,如果引用变量在赋值号左边,则它的值的改变在外部是不可见的;如果使用引用变量访问所指向的数据,则只要引用变量所指向的数据发生改变,这种改变就是外部可见的。

愚公:一休的进步就是快,但对字符串我们还要进一步体会它。写程序与写文章一样,读多了就会写了!

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务