日期:2014-05-20  浏览次数:20752 次

String的问题。。我真的不想日经 我已经搜索精华帖半天了。。
各种陈年老帖中都在说创建了几个字符串对象之类的。

我想问个intern()的问题,API的原文如下:

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

我想问一下,这段话中的“Otherwise, this String object is added to the pool”是说把堆中的String对象“剪切”到常量池中了么?或者说运行完String.intern(),堆中的字符串对象还存在么?

老帖子里面都说
String str1 = new String("aaa");
是创建了两个字符串对象,一个在常量池中一个在堆中。

我的问题是:如果是这样的话this String object is added to the pool是怎么发生的?

------解决方案--------------------
享元模式,比较复杂。需要多了解下这个模式的其它信息。

但享元模式对于new出来的实例,并无法有效处理;反过来说只有编译期能确认的,String的享元才能发挥效用。

所以你看到:
String a = "aaa";
String b = "aaa";

这里面两个aaa可以被共享。

另外有趣的是:
String a = "aaa";
String b = new String(a);
System.out.println(a==b);
b=b.intern();
System.out.println(a==b);

你猜猜看两次println的结果是什么?!


这个帖子说的比较详细,你认真看看吧:
http://blog.csdn.net/huangbiao86/article/details/6384269

------解决方案--------------------
我的问题是:如果是这样的话this String object is added to the pool是怎么发生的?

首先要搞明白“编译时”和“运行时”两个概念。

java源文件被javac编译器编译以后,生成class文件,class文件里面就包含了常量池的信息。
因此,“何时”被添加到常量池的,肯定是在编译时。

public class Test{
public static void main(String args[]){
String str = new String("aaa");
}
}
字节码:
public static void main(java.lang.String[]);
Code:
Stack=3, Locals=2, Args_size=1
0: new #2; //class java/lang/String
3: dup
4: ldc #3; //String aaa
6: invokespecial #4; //Method java/lang/String."<init>":(Ljava/lang/Strin
g;)V
9: astore_1
10: return

常量池信息:
const #1 = Method #6.#15; // java/lang/Object."<init>":()V
const #2 = class #16; // java/lang/String
const #3 = String #17; // aaa