2016-02-05 71 views
0

在此代碼中,我聲明瞭一個Initialized String變量,然後打印其哈希碼,然後將其重新初始化爲另一個值,然後調用垃圾收集器清除解除引用的對象。Java中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()); 
    } 
} 
+4

儘管Object的哈希碼是從其內存地址派生而來的,但String的哈希碼是從它的值派生而來的。 –

+3

儘管@ Elogent的評論,你有問*的GC,但一個不一定已經運行。 –

+0

即使GC在您調用'System.gc()'的行上立即發生,'m'仍然指向'「JAVA」',因此不會收集實例。 –

回答

2

我認爲你誤解了hashcode的工作原理。沒有太多細節,在Java中,hashcode被用於很多事情。一個示例用於在Hash數據結構中查找項目,如HashMapHashSet

相同值的散列應始終返回相同的散列。在這種情況下,"JAVA"的哈希值應該永遠不會改變,因爲那樣會破壞Java中提出的協議。

我認爲這太複雜了,不知道字符串的hashcode是如何計算的。你可以閱讀更多關於它here。我可以給你一個例子。

比方說,你有一個類Fruit它有像形狀,顏色和重量領域。

您必須爲此課程實施equalshashcode。做這兩件事非常重要,否則你會打破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()。它檢查是否存在該hashCode的桶中的任何內容。如果有,那麼它將使用equals()方法,直到它返回true。它必須這樣做,因爲可能存在散列碼衝突。這就是爲什麼equals和hashCode應該一起實現是很重要的原因。

3

哈希碼涉及對象的相等性,而不是身份。

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 
+0

好奇,如果他使用'System.identityHashCode(Object)'會打印一個不同的值。我不認爲這會歸因於Java中的String interning。 –