【问题标题】:String object creation using new and its comparison with intern method使用new创建字符串对象及其与intern方法的比较
【发布时间】:2012-05-13 10:55:01
【问题描述】:

我在 Kathy Sierra 的书中读到,当我们使用像 String s = new String("abc") 这样的 new 运算符创建 String 时,因为我们使用了 new 关键字,Java 将在正常情况下创建一个新的 String 对象(非池) 内存,s 将引用它。此外,文字“abc”将被放置在池中。

intern() 表示如果 String 池中已经包含一个字符串,则返回池中的字符串,否则,将 String 对象添加到池中并返回对该 String 对象的引用。

如果使用 new 创建的字符串 "abc" 也将字符串放入池中,则 intern() 表示如果字符串池包含字符串,则返回池中的字符串,否则将字符串对象添加到池中。

另外我想知道如果我们使用 new 创建一个 String 那么实际上创建了多少个对象?

【问题讨论】:

    标签: java string


    【解决方案1】:

    TL;DR:如果您真的需要这样做 new String("abc"),您就会知道自己需要这样做,并且会知道原因。说您永远不需要这样做是非常罕见的几乎。只需使用"abc"


    长版:

    当您拥有代码new String("abc") 时,会在不同时间发生以下情况:

    • 加载包含该代码的类时,如果带有字符 "abc" 的字符串尚未在实习池中,则会创建并放入实习池。
    • new String("abc") 代码运行时:
      • 对来自实习池的"abc" 字符串的引用被传递到String 构造函数中。
      • newString 对象通过复制传递给构造函数的String 中的字符来创建和初始化。
      • 新的String 对象返回给您。

    如果使用 new 创建的字符串“abc”也将字符串放入池中,那么为什么intern() 说如果字符串池包含字符串,则返回池中的字符串,否则将字符串对象添加到池中。

    因为这就是 intern 所做的。请注意,在字符串文字上调用 intern 是无操作的;字符串文字都是自动实习的。例如:

    String s1 = "abc";               // Get a reference to the string defined by the literal
    String s2 = s1.intern();         // No-op
    System.out.println(s1 == s2);    // "true"
    System.out.println(s1 == "abc"); // "true", all literals are interned automatically
    

    另外我想知道如果我们使用 new 创建一个 String 那么实际上创建了多少个对象?

    您至少创建一个 String 对象(新的、非实习的),可能还有两个(如果字面量尚未在池中;但同样,当类文件的字面量时,该位发生得更早已加载):

    String s1 = "abc";            // Get a reference to the string defined by the literal
    String s2 = new String(s1);   // Create a new `String` object (guaranteed)
    System.out.println(s1 == s2); // "false"
    String s3 = s2.intern();      // Get the interned version of the string with these characters
    System.out.println(s1 == s3); // "true"
    

    【讨论】:

    • 那么在我们实习新的String对象之后,使用new在堆中创建的对象会发生什么?
    • @anand: (所有这些都在堆中。)如果你 intern 新的字符串对象,那么假设没有其他未完成的引用它,它有资格进行垃圾回收,就像任何其他不再具有未完成引用的对象。 intern 返回对实习生String的引用。
    • @anand - 在这种特殊情况下,您正在运行的类/方法的代码对象将包含对实习生字符串的引用。这意味着只要类保持加载状态,表示"abc" 的字符串将保持可访问性。
    【解决方案2】:

    字符串池是一个字符串引用池。对象仅在堆中创建。

    当使用new String("abc").intern()或使用String s = "abc"之类的方法时;如果存在引用“abc”的引用,则检查字符串池。

    如果池中已经存在对“abc”的引用,并且在引用使用new String("abc") 创建的String object 的引用上调用.intern(),则new String("abc") 创建的对象符合垃圾回收条件。请参阅下面的代码以获得更清晰的信息。

    public static void main(String[] args) {
        String s = new String("abc");
        String a = s;
        System.out.println(s==a);// true
        String b = "abc";
        s = s.intern();
        System.out.println(s==a);// false
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2013-04-05
      • 2013-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多