简体   繁体   English

Java中字符串类的垃圾回收

[英]Garbage Collection for String Class in Java

In this code I have declared a Initialized a String variable and then printed its hashcode, then reinitialized it to another value and then invoked the Garbage Collector to clear the dereferenced objects. 在这段代码中,我声明了一个Initialized String变量,然后打印其哈希码,然后将其重新初始化为另一个值,然后调用Garbage Collector清除被取消引用的对象。

But when I reinitialize the String variable to its original value and print the hashcode, the same hashcode is getting printed. 但是,当我将String变量重新初始化为其原始值并打印哈希码时,将打印相同的哈希码。 How? 怎么样?

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

Hash code relates to object equality, not identity. 哈希码与对象相等性有关,与身份无关。

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

(Provided the two methods have been implemented consistently) (前提是这两种方法已实现一致)

Even if a gc were actually taking place here (and you weren't simply referencing strings in the constant pool), you wouldn't expect two string instances with the same sequence of chars not to be equal - hence, their hash codes will also be the same. 即使实际上在这里发生了gc(并且您并不仅仅是在常量池中引用字符串),您也不会期望两个具有相同char序列的字符串实例不相等-因此,它们的哈希码也将是相同的。

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

I think you are misunderstanding something about how hashcodes work. 我认为您对哈希码的工作方式有所误解。 Without going in to too much detail, in Java, hashcodes are used for many things. 在Java中,无需过多赘述,哈希码用于很多事情。 One example is used to find an item in a Hash datastructure like HashMap or HashSet . 一个示例用于在Hash数据结构(例如HashMapHashSet查找一项。

A hash of the same value should always return the same hash. 相同值的散列应始终返回相同的散列。 In this case, a hash of "JAVA" should never change because then it will break the agreement set forth in Java. 在这种情况下, "JAVA"的散列永远都不应更改,因为这将破坏Java中规定的协议。

I think it's too complicated to go about how hashcodes for String are calculated. 我认为,如何计算String的哈希码太复杂了。 You can read more about it here . 您可以在此处了解更多信息。 I can give you an example though. 我可以举一个例子。

Let's say you have a class Fruit and it has fields like shape, color and weight. 假设您有一个Fruit类,它具有形状,颜色和重量等字段。

You must implement equals AND hashcode for this class. 您必须为此类实现equals AND hashcode It is very important to do both because otherwise you are breaking the way Hashmap work. 两者都非常重要,因为否则您将破坏Hashmap的工作方式。 Let's say you make this for your hashCode() method. 假设您是为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;
}

This will generate the same hash value EVERY TIME for the two Fruit instances that are equal. 这将为两个相等的Fruit实例每次生成相同的哈希值。 That is exactly what you would want. 那正是您想要的。

Really quick, how would this be actually used in a HashMap ? 真的很快,这将如何在HashMap实际使用? Let's say you want to see if you have foo = new Fruit(); 假设您要查看是否有foo = new Fruit(); HashMap first calculates foo.hashCode() . HashMap首先计算foo.hashCode() It checks to see if there is anything in the bucket for that hashCode. 它检查是否在该hashCode的存储桶中有任何内容。 If there is then it will use the equals() method until it returns true. 如果存在,它将使用equals()方法,直到返回true。 It must do this because there might be hashcode collisions. 它必须这样做,因为可能存在哈希码冲突。 And that's why it is important why equals and hashCode should be implemented together. 这就是为什么为什么必须将equals和hashCode一起实现很重要的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM