【问题标题】:Garbage Collection for String Class in JavaJava中字符串类的垃圾收集
【发布时间】:2016-02-05 17:37:12
【问题描述】:

在这段代码中,我声明了一个 Initialized a String 变量,然后打印了它的哈希码,然后将其重新初始化为另一个值,然后调用垃圾收集器来清除取消引用的对象。

但是当我将 String 变量重新初始化为其原始值并打印哈希码时,会打印相同的哈希码。怎么样?

public class TestGarbage1 {

    public static void main(String args[]) {

        String m = "JAVA";   
        System.out.println(m.hashCode());         
        m = "java";
        System.gc();
        System.out.println(m.hashCode());
        m = "JAVA";
        System.out.println(m.hashCode());
    }
}

【问题讨论】:

  • 虽然一个对象的哈希码是从它的内存地址派生的,但字符串的哈希码是从它的值派生的。
  • 尽管有@Elogent 的评论,您已经要求 GC,但不一定运行。
  • 即使在你调用System.gc()的那一行立即发生了GC,m仍然指向"JAVA",因此不会收集该实例。
  • 请注意,您使用的常量字符串是类常量池的一部分,不会被垃圾回收。通过调用 new String(...) 创建的字符串可能会有不同的处理方式,但它仍然取决于 JVM 实现。

标签: java string hashcode


【解决方案1】:

哈希码与对象相等性有关,而不是身份。

a.equals(b) implies a.hashCode() == b.hashCode()

(前提是这两种方法的实现一致)

即使此处实际上发生了 gc(并且您不只是引用常量池中的字符串),您也不会期望具有相同字符序列的两个字符串实例不相等 - 因此,它们的哈希代码也将相同。

String a = new String("whatever");
String b = new String(a);
System.out.println(a == b); // false, they are not the same instance
System.out.println(a.equals(b)); // true, they represent the same string
System.out.println(a.hashCode() == b.hashCode()); // true, they represent the same string

【讨论】:

  • 很好奇如果他使用System.identityHashCode(Object) 会打印不同的值。我认为这不会是由于 Java 中的 String 实习。
【解决方案2】:

我认为您对哈希码的工作方式存在误解。无需过多介绍,在 Java 中,哈希码用于许多事情。一个示例用于在 HashMapHashSet 等 Hash 数据结构中查找项目。

相同值的散列应该总是返回相同的散列。在这种情况下,"JAVA" 的哈希值永远不应该改变,因为那样它将破坏 Java 中规定的协议。

我认为如何计算 String 的哈希码太复杂了。你可以阅读更多关于它的信息here。不过我可以给你举个例子。

假设您有一个类Fruit,它具有形状、颜色和重量等字段。

你必须为这个类实现equals AND hashcode。两者都做非常重要,否则你会破坏 Hashmap 的工作方式。假设您为 hashCode() 方法制作了这个。

@Override
public int hashCode() {
    int hash = 1;
    hash = hash * 17 + this.color;
    hash = hash * 31 + this.shape.hashCode();
    hash = hash * 31 + this.weight;
    return hash;
}

这将为两个相等的Fruit 实例每次生成相同的哈希值。这正是你想要的。

真的很快,这将如何在HashMap 中实际使用?假设你想看看你有没有foo = new Fruit(); HashMap 首先计算foo.hashCode()。它检查存储桶中是否有该哈希码的任何内容。如果有,那么它将使用equals() 方法,直到它返回true。它必须这样做,因为可能存在哈希码冲突。这就是为什么 equals 和 hashCode 应该一起实现很重要的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-25
    • 1970-01-01
    • 2013-02-15
    • 2010-12-13
    • 2016-08-16
    • 2011-02-25
    • 2013-05-30
    相关资源
    最近更新 更多