【问题标题】:Java Strings and StringPoolJava 字符串和字符串池
【发布时间】:2010-12-26 13:29:47
【问题描述】:
public String makinStrings() {
   String m = "Fred47";
   String s = "Fred";
   s = s + "47";
   s = s.substring(0);
   return s.toString();
} 

代码创建了多少个对象?

我做了一个简单的测试:

public static void main(String[] args) {
   String m = "a";
   m += "bc";
   String s1 = "mabc".substring(1);
   String s2 = "abc";

   System.out.println(m == "abc");
   System.out.println(m == s1);
   System.out.println(m == s2);
   System.out.println(s1 == s2);
}

如果m、s1、s2指向同一个对象(“abc”),结果不应该是“真、真、真、真”吗? 结果却是“假,假,假,假”!

【问题讨论】:

    标签: java string


    【解决方案1】:

    不,仅仅因为两个字符串相等并不意味着它们的引用相等。

    编译实习生一些字符串以节省空间,所以如果你尝试:

    String s1 = "abc";
    String s2 = "abc";
    

    那么 s1 == s2 将是真的,但这是一个特例而不是一般规则。默认情况下,运行时生成的字符串一般不共享相同的引用。

    【讨论】:

    • 我期待从字符串池中使用新的字符串对象(如果它们存在)。在 java 5.0 中,数字(整数、字节等)被缓存(至少是小数字)并在从字符串解析时重用。我期待与字符串相同,但似乎并非如此......
    • 我怀疑这是因为空间/性能的权衡对于字符串来说是不值得的,而对于 Integer 来说是不值得的,因为你在装箱时可能会得到大量相等的对象。但是您不应该依赖当前的行为 - 它可能会在未来的实施中发生变化。
    • @Mark - 正确 ... 实习 String 很昂贵,但查看 Integer 对象是否已经存在很便宜。
    【解决方案2】:

    结果在这种情况下为真 - 但ms1s2 都引用不同的字符串。对于常量字符串表达式,会自动执行 Interning,并且可以通过调用 intern 方法显式调用,但对于字符串连接和子字符串不会自动发生。

    在 Sun 的 Java 7 实现中,x.substring(0) 实际上会再次返回相同的引用 (x),但我认为 API 无法保证这一点。

    看看你的例子:

    public String makinStrings() {
       String m = "Fred47";
       String s = "Fred";
       s = s + "47";
       s = s.substring(0);
       return s.toString();
    }
    

    前两行要求内存中有两个字符串,但我不确切知道何时可以保证创建对象。一旦它们已经被创建,它们就会继续存在 - 所以再次调用 makinStrings 将不会在这两行中创建更多。

    字符串连接创建一个新的字符串对象。

    substring 调用不会在我看过的实现中创建一个新的字符串对象 - 但它可以。

    s.toString() 的调用不会创建一个新字符串(这在JavaDoc 中指定)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多