2013-06-18 57 views
0

我有這樣的代碼由其他人編寫,我很難理解它。此代碼背後的邏輯說明 - Java

這是工作的罰款,併產生正確的結果,但我不明白它是如何工作

package you; 

import clowns.Clown; 
import clowns.Volkswagen; 

public class You { 
static int counter = 0; 
static Volkswagen vw = new Volkswagen(); 

public static void main(String args[]) { 
    vw.add(new RecursiveClown()); 
    vw.done(); 
} 

static class RecursiveClown extends Clown { 
    public int hashCode() { 
     if (++counter < 20) { 
      vw.add(new RecursiveClown()); 
     } 
     return super.hashCode(); 
    } 
} 
} 

無法理解,顯然RecursiveClown不會被調用的任何地方既不其hashcode()功能

那麼如何來吧它的作品,並添加RecursiveClown對象。

也是爲什麼它返回super.hashCode();

還有這等類,這是上面代碼中引用。這兩類

package clowns; 

import java.util.HashSet; 
import java.util.Set; 

public class Volkswagen { 
private static final int CAPACITY = 5; 
private Set<Clown> clowns = new HashSet<Clown>(); 

public synchronized void add(Clown clown) { 
    if (clowns.size() >= CAPACITY) { 
     throw new IllegalStateException("I'm full"); 
    } else { 
     clowns.add(clown); 
    } 
} 

public synchronized void done() { 
    if (clowns.size() == 20) { 
     // The goal is to reach this line 
     System.out.println("I'm a Volkswagen with 20 clowns!"); 
    } 
} 
} 

輸出是:I'm a Volkswagen with 20 clowns!

但每當我在 '大衆' add()方法印刷

clowns.size() 

,它總是返回0,那麼爲什麼它比較

clowns.size() == 20 

並將其評價爲真實?

回答

0

該代碼依靠HashSet依靠.hashCode()

當一個元素插入到HashSet中時,該實現Set通過首先調用要添加的元素.hashCode()來確定該元素的唯一性;當且僅當散列碼等於另一個時才考慮.equals()

它返回super.hashCode(),因爲這是Object的一個:Clown不覆蓋它。

由於RecursiveClown延伸了Clown,所以可以將其添加到ClownSets。當添加一個,.hashCode()增加了另一個遞歸小丑到大衆,直到達到counter 20.

1

Set<Clowns>HashSet,它本身就是備份由HashMap。 所以,基本上,當你添加一個對象到Set<Clowns>時,它會調用HashMap.put()

HashMap.put()調用所提供對象的hashCode()方法。 這就是爲什麼你的對象的hashCode()方法沒有明確的調用被調用。

2

爲什麼你的大衆汽車含有比其容量更多的小丑的解釋是因爲小丑的添加方式。

它實質上是在方法Volkswagen.add()

clowns.add(clown); 

內。它首先調用小丑的hashCode,然後將其添加到其內部結構中。由於hashCode遞歸再次調用Volkswagen.add(),在這一點是沒有添加小丑到(內部數據結構背襯)HashSet,從而size()返回0

這樣在開始方法Volkswagen.add()的未達到的能力,但只有退出此方法時(因爲只有小丑實際上被添加到HashSet)。

1

功能HashSet.add將作爲FGE提到的,檢查對象的hashcode,它被添加之前,這意味着添加小丑#1之前,用於小丑#2的Volkswagan.add函數被調用。

隨後,直到hashcode函數中有20個深度遞歸,並且一旦終止所有20個小丑,就一次添加。