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));
 }
} 

输出:

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

我的问题:

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

2.会发生什么"String s2 = "abc"?我想没有创建任何对象。但这是否意味着 Java 解释器需要搜索所有的实习字符串?这会导致任何性能问题吗?

String s3 = new String("abc") 3.似乎不使用interned string。为什么?

4.会String s5 = new String("def")创建任何新的实习字符串吗?

4

4 回答 4

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

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

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

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

3-4 处的 String 对象没有被实习。

于 2012-05-20T09:58:21.000 回答
3

1. "String s1 = "abc" 会发生什么?

在编译时,文字的表示被写入包含此代码的类的类文件的“常量池”部分。

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

在运行时,对先前创建/实习的 String 的引用被分配给s1. (执行此语句时不会发生字符串创建或实习。)

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

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

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

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

2. "String s2 = "abc" 会发生什么?

加载时没有任何反应。当编译器创建类文件时,它为第一次使用文字时使用的文字重用了相同的常量池条目。因此,此语句使用的 String 引用与前一个语句使用的相同。

我想没有创建任何对象。

正确的。

但这是否意味着 Java 解释器需要搜索所有的实习字符串?这会导致任何性能问题吗?

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

3.似乎String s3 = new String("abc")不使用interned string。为什么?

它比这更复杂。构造函数调用使用内部字符串,然后创建一个新字符串,并将内部字符串的字符复制到新字符串的表示中。新创建的字符串分配给s3.

为什么?因为new指定为总是创建一个新对象(参见 JLS),而String构造函数被指定为复制字符。

4. String s5 = new String("def") 会创建任何新的实习字符串吗?

在加载时创建一个新的实习字符串(对于“def”),然后在运行时创建一个新的 String 对象,它是实习字符串的副本。(有关详细信息,请参阅前面的文本。)

于 2012-05-20T10:53:48.037 回答
2

在 SO 上看到这个答案。另请参阅有关字符串实习的维基百科文章。

于 2012-05-20T09:58:30.960 回答
-1

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

String s2 = "abc";s1将从实习生池中拖动相同的对象。JVM 这样做是为了提高性能。它比创建新字符串更快。

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

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

于 2012-05-20T09:52:59.030 回答