java string 几个对象,String s = new String(\"abc\")创建几个对象-bjutslg-ChinaUnix博客

String str=new String("abc");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢?

相信大家对这道题并不陌生,答案也是众所周知的,2个。

接下来我们就从这道题展开,一起回顾一下与创建String对象相关的一些JAVA知识。

我们可以把上面这行代码分成String

str、=、"abc"和new String()四部分来看待。String

str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;=是对变量str进行初始化,将某个对象的引用(或者叫句柄)赋值给

它,显然也没有创建对象;现在只剩下new String("abc")了。那么,new

String("abc")为什么又能被看成"abc"和new String()呢?

我们来看一下被我们调用了的String的构造器:

public String(String original) {  //other code ...  }   大家都知道,我们常用的创建一个类的实例(对象)的方法有以下两种:

一、使用new创建对象。

二、调用Class类的newInstance方法,利用反射机制创建对象。

我们正是使用new调用了String类的上

面那个构造器方法创建了一个对象,并将它的引用赋值给了str变量。同时我们注意到,被调用的构造器方法接受的参数也是一个String对象,这个对象正

是"abc"。由此我们又要引入另外一种创建String对象的方式的讨论——引号内包含文本。

这种方式是String特有的,并且它与new的方式存在很大区别。

String str="abc";

毫无疑问,这行代码创建了一个String对象。

String a="abc";  String b="abc";   那这里呢?

答案还是一个。

String a="ab"+"cd";   再看看这里呢?

答案是三个。

说到这里,我们就需要引入对字符串池相关知识的回顾了。

在JAVA虚拟机(JVM)中存在着一个字符

串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。由于String类是final的,它的值一经创建就不可改变,因此我们

不用担心String对象共享而带来程序的混乱。字符串池由String类维护,我们可以调用intern()方法来访问字符串池。

我们再回头看看String

a="abc";,这行代码被执行的时候,JAVA虚拟机首先在字符串池中查找是否已经存在了值为"abc"的这么一个对象,它的判断依据是String

类equals(Object

obj)方法的返回值。如果有,则不再创建新的对象,直接返回已存在对象的引用;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返

回。因此,我们不难理解前面三个例子中头两个例子为什么是这个答案了。

只有使用引号包含文本的方式创建的

String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的

新对象都不会被加入字符串池中,对此我们不再赘述。因此我们提倡大家用引号包含文本的方式来创建String对象以提高效率,实际上这也是我们在编程中常

采用的。

栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。

堆(heap):用于存储对象

所以对于语句String s = new String("XYZ") + new String("XYZ");

近在论坛上看到关于String s = new String("XYZ") + new String("XYZ");到底创建几个对象的讨论,觉得比较有意思,在此总结一下。

在JAVA中除了8种基本类型之外,其他的都是类对象及其引用。所以 "XYZ"在JAVA中是一个String对象,对于String类对象来说它的对象值是不能修改的,也就是具有不变性。

但是在下面一段程序中:

publicclassTestString {

publicstaticvoidmain(String args[]) {

String s = "Hello";

s = "Java";

String s1 = "Java";

String s2 = newString("Java");

System.out.println(s);

System.out.println(s == s1);

System.out.println(s == s2);

}

}

/*output:

*Java

*true

*false

*/

打印出s的结果是"Java",看起来s所引用的String变量好像是被修改了,但是如果你了解JVM(Java虚拟机)处理String变量时的机制,你就会知道事实并非如此。

在JVM的工作过程中,会创建一片的内存空间专门存入String对象,我们把这片内存空间叫做String池。

对于语句String s= "Hello";,当JVM看到"Hello"时,会在String池创建String对象存储它,并将它的引用返回给String变量s。

语句s = "Java";,当JVM看到"Java"时,会在String池创建新的String对象存储它,再把新建的String对象的引用返回给String变量s。而原先的String对象"Hello"仍然在String池内,并没有消失,它是不能被修改的。

所以我们仅仅是改变了变量s的引用,而没有改变它所引用的对象,因为String对象的值是不能被修改的。

String s1 =

"Java";,JVM首先在String池里面看能否找到字符串"Java",如果找到则返回它的引用给s1,否则创建新的String对象,放到

String池里。这里由于有s = "Java",所以对象已经被引用,所以依据规则s和s1都是引用同一个对象。所以s==s1返回true。(注:

比较运算符==,对于非基本类型,是比较两引用是否引用内存中的同一个对象)。

String s2 = new String( "Java");,JVM首先还是在String池里面看能否找到字符串

"Java",如果找到,不做任何事情;否则创建新的String对象,放到String池里面。由于遇到了new关键字,还会在内存上(不是

String池里面)创建String对象存储

"Java",并将内存上的(不是String池里面的)String对象返回给s2。所以s==s2将返回false,因为它们引用的不是同一个对象。

所以对于语句String s = new String("XYZ") + new String("XYZ");

JVM先在String池中创建一个String对象存储"XYZ",然后由于遇到new关键字,再在内存上创建一个String对象存储"XYZ";

接着由于String池中已经有了"XYZ"的对象,所以第二个new语句不会在String池中创建对象,而只会在内存上创建一个String对象;

最后两个字符串相加会在String池中创建一个String对象"XYZXYZ",并将其引用传给s。(因为最后一个相加只是+没有new所以只在String池中有,内存堆上不会有)

所以总共会创建4个String对象。

3、String、StringBuffer、StringBuilder的联系与区别

上面已经分析了String的本质了,下面简单说说StringBuffer和StringBuilder。 StringBuffer和StringBuilder都继承了抽象类AbstractStringBuilder,这个抽象类和String一样也定义了char[] value和int count,但是与String类不同的是,它们没有final修饰符。因此得出结论:String、

StringBuffer和StringBuilder在本质上都是字符数组,不同的是,在进行连接操作时,String每次返回一个新的String实

例,而StringBuffer和StringBuilder的append方法直接返回this,所以这就是为什么在进行大量字符串连接运算时,不推荐

使用String,而推荐StringBuffer和StringBuilder。那么,哪种情况使用StringBuffe?哪种情况使用StringBuilder呢?关于StringBuffer和StringBuilder的区别,翻开它们的源码,下面贴出append()方法的实现。

uid-28811518-id-5709050.html

uid-28811518-id-5709050.html

上面第一张图是StringBuffer中

append()方法的实现,第二张图为StringBuilder对append()的实现。区别应该一目了然,StringBuffer在方法前加了

一个synchronized修饰,起到同步的作用,可以在多线程环境使用。为此付出的代价就是降低了执行效率。因此,如果在多线程环境可以使用StringBuffer进行字符串连接操作,单线程环境使用StringBuilder,它的效率更高。

转自:

http://my.oschina.net/xiaohui249/blog/170013

http://www.cnblogs.com/ydpvictor/archive/2012/09/09/2677260.html

http://blog.csdn.net/wuxianglong/article/details/6119399

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值