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 对象以提高效率, 实际上这也是我们在编程中常采用的.
String s=new String("abc")创建了几个对象?
来源: http://www.bubuko.com/infodetail-3365916.html