代码背后的逻辑解释-Java

代码背后的逻辑解释-Java,java,jakarta-ee,logic,inner-classes,hashcode,Java,Jakarta Ee,Logic,Inner Classes,Hashcode,我有其他人写的代码,我很难理解它 它工作正常,产生正确的结果,但我不明白它是如何工作的 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 Rec

我有其他人写的代码,我很难理解它

它工作正常,产生正确的结果,但我不明白它是如何工作的

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();
    }
}
}
这两个类的输出是:
我是一辆有20个小丑的大众汽车

但每当我打印

clowns.size() 
在“Volkswagen”的
add()
方法中,它总是返回0,那么它是如何比较的呢

clowns.size() == 20

并将其求值为true?

代码依赖于
HashSet
自身依赖于
.hashCode()

当一个元素被插入到
HashSet
中时,
Set
的这个实现通过首先调用要添加的元素上的
.hashCode()
来确定元素的唯一性;当且仅当哈希代码等于另一个哈希代码时,才考虑
.equals()

它返回super.hashCode(),因为这是
对象
的一个:
小丑
不会覆盖它


由于
递归小丑
扩展了
小丑
,因此可以将其添加到
小丑
集合
。当添加一个时,
.hashCode()
向大众汽车添加另一个递归小丑,直到
计数器达到20。

代码依赖于
HashSet
依赖于
.hashCode()

当一个元素被插入到
HashSet
中时,
Set
的这个实现通过首先调用要添加的元素上的
.hashCode()
来确定元素的唯一性;当且仅当哈希代码等于另一个哈希代码时,才考虑
.equals()

它返回super.hashCode(),因为这是
对象
的一个:
小丑
不会覆盖它

由于
递归小丑
扩展了
小丑
,因此可以将其添加到
小丑
集合
。当添加一个时,
.hashCode()
向大众汽车添加另一个递归小丑,直到
计数器达到20。

集是一个
HashSet
,它本身由
HashMap
备份。 因此,基本上,当您向
集合添加对象时,它将调用
HashMap.put()

HashMap.put()
调用所提供对象的
hashCode()
方法。 这就是调用对象的
hashCode()
方法而不显式调用的原因。

Set
是一个
HashSet
,它本身由
HashMap
备份。 因此,基本上,当您向
集合添加对象时,它将调用
HashMap.put()

HashMap.put()
调用所提供对象的
hashCode()
方法。
这就是为什么在没有显式调用的情况下调用对象的
hashCode()
方法。

大众汽车包含的小丑数量超过其容量的原因是添加小丑的方式

它基本上在这条线之内

clowns.add(clown);
在方法
Volkswagen.add()
中。它首先调用要添加的小丑的
hashCode
,然后将其添加到其内部结构中。由于
hashCode
再次递归调用
Volkswagen.add()
,此时小丑尚未添加到(内部数据结构备份)
HashSet
,因此
size()
返回0


这样一来,容量在方法
Volkswagen.add()
开始时不会达到,但只有在退出此方法时才会达到(因为只有这样,小丑才会实际添加到
哈希集
)。

大众汽车包含的小丑数量超过其容量允许的原因在于小丑的添加方式

它基本上在这条线之内

clowns.add(clown);
在方法
Volkswagen.add()
中。它首先调用要添加的小丑的
hashCode
,然后将其添加到其内部结构中。由于
hashCode
再次递归调用
Volkswagen.add()
,此时小丑尚未添加到(内部数据结构备份)
HashSet
,因此
size()
返回0


这样,容量在方法
Volkswagen.add()
开始时不会达到,但只有在退出此方法时才会达到(因为只有这样小丑才会实际添加到
HashSet
)。

函数
HashSet.add
将如fge所述,在添加对象之前检查对象的
hashcode
,这意味着在添加小丑1之前,将调用小丑2的
Volkswagan.add
函数


直到hashcode函数中有20个深度的递归,并且一旦终止,所有20个小丑都将一次添加。

函数
HashSet.add
将如fge所述,在添加对象之前检查对象的
hashcode
,这意味着在添加小丑1之前,调用小丑2的
Volkswagan.add
函数

这一直持续到hashcode函数中有20个深度的递归,一旦终止,所有20个小丑将一次添加