2012-05-20 35 views
6
class A { 

String s4 = "abc"; 

static public void main(String[]args) { 

     String s1 = "abc"; 
     String s2 = "abc"; 
     String s3 = new String("abc"); 
     A o = new A(); 
     String s5 = new String("def"); 

     System.out.println("s1==s2 : " + (s1==s2)); 
     System.out.println("s1==s1.intern : " + (s1==s1.intern())); 
     System.out.println("s1==s3 : " + (s1==s3)); 
     System.out.println("s1.intern==s3.intern : " + (s1.intern()==s3.intern())); 
     System.out.println("s1==s4 : " + (s1==o.s4)); 
} 
} 

输出:的Java:文字字符串

s1==s2 : true 
s1==s1.intern : true 
s1==s3 : false 
s1.intern==s3.intern : true 
s1==s4 : true 

我的问题:

1.什么发生了"String s1 = "abc"?我猜字符串对象被添加到类String中的池作为一个interned字符串?它放在哪里? “永久代”或只是堆(作为String类实例的数据成员)?

2. "String s2 = "abc"发生了什么?我猜想没有任何对象被创建。但这是否意味着Java Intepreter需要搜索所有被拦截的字符串?这会导致任何性能问题?

3.Seems String s3 = new String("abc")不使用interned string.Why?

4.请问String s5 = new String("def")创建任何新的interned字符串?

回答

3

1.什么情况为“字符串S1 =‘ABC’?

在字面的表示被写入到编译时间‘的类文件用于包含类的常量池’的一部分这段代码。

当加载类时,会读取类文件常量池中字符串文字的表示形式,并从中创建一个新的String对象。然后这个字符串被执行,然后对代码中的字符串的引用被“嵌入”。

在运行时,对以前创建的/实行字符串的引用被分配到s1。 (在执行该语句时没有字符串创建或实习情况。)

我猜String对象添加到String类池作为实习字符串?

是的。但是代码执行时不行。

它放在哪里? “永久代”或只是堆(作为String类实例的数据成员)?

它存储在堆的PermGen的区域。 (String类没有静态字段。JVM的字符串池在本机代码实现。)

2.什么发生的“串S =‘ABC’?

什么也没有发生在加载时。当编译器创建了类文件时,它重用了用于文本首次使用的文字的同一个常量池条目,所以该语句所使用的字符串引用与前一条语句使用的字符串引用相同。

我想没有任何物体被创造出来

正确。

但这是否意味着Java Intepreter需要搜索所有被拦截的字符串?这会导致任何性能问题?

否,否。Java解释器(或JIT编译的代码)使用与以前的语句创建/嵌入相同的引用。

3.Seems String s3 = new String(“abc”)不使用interned string.Why?

它比这更复杂。构造函数调用使用 interned字符串,然后创建一个新的String,并将实例化字符串的字符复制到新String的表示形式。新创建的字符串分配给s3

为什么?因为new指定的始终创建一个新对象(请参阅JLS),并且String构造函数是指定作为复制字符。

4.Will String s5 = new String(“def”)create new interned string?

甲新实习串在加载时创建的(为“DEF”),然后在运行时它是一个复制实习串的创建新的字符串对象。 (有关更多详细信息,请参阅上一段文字。)

+0

谢谢mate.Your答案看起来不错。还有一个问题:如果文字被写入类文件的“常量池”部分,2个类中的2个文字(相同内容)如何使用相同的实际字符串? –

+0

@DonLi - 常量池是类文件的一部分。 classfile规范不允许一个类文件引用另一个类文件的常量池。 –

-1

String s1 = "abc";创建一个新的字符串并实施它。

String s2 = "abc";将从intern池中拖动用于s1的相同对象。 JVM这样做可以提高性能。它比创建一个新的字符串更快。

调用new String()是多余的,因为它会返回一个新的隐式字符串对象。 不是从实习生池中检索它。

正如Keyser所说,==比较了字符串对象的相等性,如果它们是相同的对象,则返回true。当比较字符串的内容,你应该使用.equals()

+0

哪一部分我说错了? – Jivings

+0

段1在编译时创建一个新的String。第2段同上:JVM与它无关。 – EJP

+0

在你编辑(和关闭)你的答案之前,当你说“abc”和新字符串(“abc”)是相同的东西时,我已经低估了。 –

5
  1. 编译创造了“ABC” 在常量池中,一个String对象,并生成字节码的赋值语句对它的引用。

  2. 参见(1)。没有搜索;没有性能问题。

  3. 这会在运行时创建一个新的String对象,因为这就是'new'操作符所做的:创建新对象。

  4. 是的,对于“def”,但由于(3)一个新的字符串也在运行时创建。

3-4中的字符串对象不被拦截。

+1

编译器在常量池中创建一个String文字。但是,当类被加载时,这被解析为引用。 – Jivings

+0

这个答案仍然是错误的。 – Jivings

+0

@Jivings错误如何?这样的评论对任何人都没有用。 – EJP

2

查看this的答案。另请参阅this关于字符串实习的维基百科文章。