-------参考Java面试解惑:究竟创建了几个对象?
问题提出:
一. String abc=new String("abc");究竟创建了几个String对象?(2个 )
把改式子分解为:
1. String abc 声明了一个变量,没产生新对象
2. = 赋值操作,也没产生新对象
3. new String 新生成了一个对象
4. ''abc" 新生成了一个对象
解释:
根据String类的构造函数:
public String(String original)
{
//other code
}
String abc=new String(“abc”);
实际等价于:
original=”abc”;然后把引用赋值给abc;
根据jdk文档:
original=”abc”;
等价于
char data[] = {'a', 'b', 'c'};
String original = new String(data);
编译器是如何操作的:
(*) JVM会先在Stack区中,创建三个char型值为'a', 'b', 'c',然后在Heap中创建一个对象original,它的值为刚刚Stack中刚刚三个char型组成的数组。
Stack区存放基本类型(即常量类型,int,char,boolean,long,short,byte,double,float),特别速度快,可以共用 比寄存器速度稍慢,比Heap快
Heap区存放对象
二.String abc=”abc”创建了几个对象 ? (1个,根据问题一的分析)
三. String abc=”abc”;
String abc1=”abc”;
创建了几个对象? (1个)
JVM维护一个String Pool(字符串池),存放运行时产生的各种字符串,Pool中存放的字符串不重复。
当String abc=”abc”代码被执行(编译)时,JVM首先在String Pool中查找是否有”abc”,如果没有,则参照(*)创建新对象,并把该对象加入到Pool中。
当执行String abc1=”abc”时,JVM在String Pool中找到有”abc”,,故直接返回其引用而不创建新的对象。
[上面的操作,使用的String的public native String intern() 调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。用代码来说明intern的用法
public class InternTest {
public static void main(String args[])
{
String abcd=new String(new char[] {'a','b','c','d'});
String abcd1=abcd.intern();//abcd用字符数组初始化的,
//String Pool中没有"abcd"对象
//创建新的对象
if(abcd==abcd1)
System.out.println("abcd1与abcd指向同一个对象");
else
System.out.println("abcd1与abcd不是指向同一个对象");
String abcd2=abcd1.intern();//String Pool中有"abcd" 不会创建新的对象
if(abcd2==abcd1)
System.out.println("abcd1与abcd2指向同一个对象");
else
System.out.println("abcd1与abcd2不是指向同一个对象");
}
}
输出结果为:
abcd1与abcd不是指向同一个对象
abcd1与abcd2指向同一个对象