Topic: 关于String的老问题,高手给指点一下

  Print this page

1.关于String的老问题,高手给指点一下 Copy to clipboard
Posted by: andy_wang_5
Posted on: 2007-08-14 12:02

String str = "abc"; 创建了几个对象,为什么?请说明
String str = new String("abc"); 创建了几个对象,为什么?请说明

2.Re:关于String的老问题,高手给指点一下 [Re: andy_wang_5] Copy to clipboard
Posted by: JiafanZhou
Posted on: 2007-08-15 00:03

andy_wang_5 wrote:
String str = "abc"; 创建了几个对象,为什么?请说明

有可能是一个,或者根本没有创建对象。

andy_wang_5 wrote:
String str = new String("abc"); 创建了几个对象,为什么?请说明

一个对象。

关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:

(1)先定义一个名为str的对String类的对象引用变量:String str;

(2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象o,并将o 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。

(3)将str指向对象o的地址。

关于String str = new String("abc")的内部工作
只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。

String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。

结论与建议:
(1)我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向 String类的引用被创建了。至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。

(2)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。

(3)当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==。

(4)由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

参考:http://www.duduwolf.com/post/3.asp

3.Re:关于String的老问题,高手给指点一下 [Re: andy_wang_5] Copy to clipboard
Posted by: andy_wang_5
Posted on: 2007-08-15 11:06


4.Re:关于String的老问题,高手给指点一下 [Re: andy_wang_5] Copy to clipboard
Posted by: Cappuccino
Posted on: 2007-08-18 02:44

二楼的回答不错,自己又学到不少东西。

补充扩展一下:
1. 对于String扩充且不考虑线程安全时,更应该使用StringBuilder,好像是jdk1.5增加的,因为不支持同步,所以比StringBuffer更快一些。

2. 想起来其实对于int也有类似的问题。new Integer会显式的的在内存中创建对象,而直接Integer xx = num并不一定会创建新的对象。比方说下面这个例子:
    for(int i=0;i<200;i++)
    {
      Integer a = i;
      Integer b = i;
      System.out.println(a==b);
    }


因为jdk会在内存里缓存-128到127之间的数值,所以当有新的对象对其进行引用时,不会new一个新的对象,所以这个范围内a和b的地址都是相同的。而当超出这个界限时Jdk就需要新建一个内存空间了,自然地址也就不等了。

5.Re:关于String的老问题,高手给指点一下 [Re: andy_wang_5] Copy to clipboard
Posted by: kulatasana
Posted on: 2007-08-22 12:22

参照设计模式中的享元模式(Flyweight)能够更好的理解

6.Re:关于String的老问题,高手给指点一下 [Re: andy_wang_5] Copy to clipboard
Posted by: JiafanZhou
Posted on: 2007-08-22 22:32

And the concept of "Heap", "Stack", "Memory allocation" are fully discussed in "Thinking in Java". This book is the bible for all the Java developers.


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923