为什么在Tiger Book的符号表中串实习生?

时间:2016-03-30 07:28:12

标签: java string-interning

在第5.1.4章中, Java中的现代编译器实现

public class Symbol {
  private String name;
  private Symbol (String n) { name = n; }
  private static java.util.Dictionary dict = new java.util.Hashtable();

  public String toString() { return name; }

  public static Symbol symbol(String n) {
    String u = n.intern();
    Symbol s = (Symbol)dict.get(u);
    if (s == null) { s = new Symbol(u); dict.put(u, s); }
    return s;
  }
}

我无法理解为什么在这里使用字符串实习生,因为Hashtable使用key.equals(...)来检查身份。

你可以告诉我原因吗?谢谢!

2 个答案:

答案 0 :(得分:1)

在编程方面,有很多"智慧","谣言","魔术"或者"迷信"到处走走。

正如@RealSkepic所指出的,在Java 7u4之前,String.substring将使用原始字符串的一部分而不是复制该部分。虽然这在许多情况下改善了性能,但它可能导致内存泄漏。使用intern()是避免这种情况的一种方法,尽管它可以创建它自己的内存清理问题,这是不理想的。使用new String(oldString)是另一种方法,但您现在不应该这样做。

人们经常会因为性能原因而尝试事情。但不知道如何测试它,或者只是不检查它实际上有帮助。我不时这样做,即使我知道要避免它,因为它经常是不正确的,或者只是让代码混乱。

作者很可能发现了一种情况,或者听说有人使用String.intern()节省了大量内存,在特定情况下,它可以做到这一点,但它不像你撒上的仙尘一点性能魔术,一切都更好。大多数这些用于优化代码的模糊技巧仅适用于非常特定的用例。

类似的例子是人们在多线程中使用锁或线程安全集合。充分利用这一点并且程序似乎可以阻止错误,但是您还没有真正解决问题,只是在发生偶然更改并且您的错误再次出现时更难找到。

答案 1 :(得分:1)

我希望你知道String#intern的作用。简单地说,它将把给定字符串添加到由String类维护的字符串池中(如果它已经不是它的一部分),或者如果该字符串已经是String池的一部分,则返回该对象。因此,字符串池中只有String的特定值的副本。

这意味着当我们执行aString.intern()时,这总是放在地图中,下次从地图获取anotherString.intern()时,等于将在{{1}中返回true比较本身。这将避免遍历整个字符串以验证相等性。如果存储在地图中的字符串可能很大并且要经常搜索(获取或包含操作)Map,那么这可以证明是一个很好的性能改进。