黑马程序员技术交流社区

标题: String s = new String("xyz");创建了几个String Object? [打印本页]

作者: 张会文    时间: 2013-1-1 14:48
标题: String s = new String("xyz");创建了几个String Object?
本帖最后由 张会文 于 2013-1-1 16:42 编辑

String s = new String("xyz");创建了几个String Object? 为什么?
作者: 王少雷    时间: 2013-1-1 14:57
2个
一个是你的Class被CLassLoader加载时,你的"xyz"被作为常量读入,在constant   pool里创建了一个共享的"xyz"  , 然后,当调用到new   String("xyz")的时候,会在heap里创建这个new   String("xyz");
作者: 嘿嘿小学徒    时间: 2013-1-1 15:02
我们可以把上面这行代码分成String str、=、"xyz"和new String()四部分来看待。String str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;=是对变量str进行初始化,将某个对象的引用(或者叫句柄)赋值给它,显然也没有创建对象;现在只剩下new String("xyz")了。那么,new String("xyz")为什么又能被看成"xyz"和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对象以提高效率,实际上这也是我们在编程中常采用的。



肯定可以帮到你


作者: 王玮    时间: 2013-1-1 15:08
本帖最后由 王玮 于 2013-1-1 15:09 编辑

我的理解是:new String(); 直接在对内存创建一个对象,然后再字符串常量池里面去寻找 是否有“xyz”,有就把值赋给 刚在内存创建的那个对象。最后把地址赋给s

=====================================================================================================
这是一点总结:第一:对于 String s2 = new String("abc") ,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址
第二:对于 String   s1  =   "abc ";先定义一个名为s1的对String类的对象引用变量:String   s1;,然后,在栈中(字符串常量池)查找有没有存放值为 "abc "的地址,如果没有,则开辟一个存放字面值为 "abc "的地址,接着创建一个新的String类的对象s,并将s 的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象s。如果已经有了值为 "abc "的地址,则查找对象s,并返回s的地址。最后,将s1指向对象s的地址。

作者: 奋斗的青春    时间: 2013-1-1 15:09
本帖最后由 吴愿涛 于 2013-1-1 15:10 编辑

我就不多言了,关注下基础!
作者: 郝福明    时间: 2013-1-1 15:14
1个类型变量 + 1个String Object




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2