我有这个代码是由别人写的,我很难理解它。
工作正常并产生正确的结果,但我无法理解它是如何工作的
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!
但每当我打印
clowns.size()
在'大众汽车'的add()
方法中,它总是返回0然后如何比较
clowns.size() == 20
并将其评估为真?
答案 0 :(得分:2)
解释为什么你的大众汽车包含比它的容量更多的小丑是因为小丑的添加方式。
它基本上在行
之内clowns.add(clown);
方法Volkswagen.add()
中的。它首先调用小丑的hashCode
,然后将其添加到其内部结构中。由于hashCode
递归地再次调用Volkswagen.add()
,此时小丑尚未添加到(内部数据结构支持)HashSet
,因此size()
返回0.
这种方式在方法Volkswagen.add()
开始时未达到容量,但仅在退出此方法时才会达到(因为只有小丑实际上被添加到HashSet
)。
答案 1 :(得分:1)
Set<Clowns>
是HashSet
,它本身由HashMap
备份。
因此,基本上,当您向Set<Clowns>
添加对象时,它将调用HashMap.put()
。
HashMap.put()
调用所提供对象的hashCode()
方法。
这就是为什么在没有显式调用的情况下调用对象的hashCode()
方法的原因。
答案 2 :(得分:1)
如上所述,函数HashSet.add
将在添加之前检查对象的hashcode
,这意味着在添加小丑#1之前,Volkswagan.add
函数小丑#2被称为。
直到hashcode函数中有20个深度递归为止,一旦终止,所有20个小丑都会一次性添加。
答案 3 :(得分:0)
代码依赖HashSet
依靠.hashCode()
。
当一个元素插入HashSet
时,Set
的这个实现通过首先在要添加的元素上调用.hashCode()
来确定元素的唯一性;当且仅当哈希码等于另一个哈希码时才考虑.equals()
。
它返回super.hashCode(),因为这是Object
的一个:Clown
不会覆盖它。
由于RecursiveClown
扩展了Clown
,因此可以将其添加到Set
Clown
。添加一个时,.hashCode()
会向大众汽车添加另一个递归小丑,直到counter
达到20。