Java HashSet addAll方法修改类内部字段

Java HashSet addAll方法修改类内部字段,java,hashset,Java,Hashset,我有一个类,它扩展了HashSet的参数化版本。此类有一个内部字段currentSize,用于跟踪到目前为止添加了多少元素。子类重写基类“add和addAll方法,因此currentSize相应增加。我的问题是在addAll中,集合的大小被添加到currentSize计数器中两次,而不是一次。下面是我的班级代码: public class InheritHashSet extends HashSet<Integer> { private int currentSize = 0

我有一个类,它扩展了HashSet的参数化版本。此类有一个内部字段
currentSize
,用于跟踪到目前为止添加了多少元素。子类重写基类“
add
addAll
方法,因此
currentSize
相应增加。我的问题是在
addAll
中,集合的大小被添加到
currentSize
计数器中两次,而不是一次。下面是我的班级代码:

public class InheritHashSet extends HashSet<Integer> {
    private int currentSize = 0;

    @Override
    public boolean add(Integer e) {
        currentSize++;
        super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends Integer> e) {
        currentSize += e.size();
        super.addAll(e);
    }

    public int getCurrentSize() {
        return currentSize;
    }
}

看起来调用
super.addAll(e)
也会修改
currentSize
(这似乎毫无意义)

扩展现有集合类几乎从来都不是一个好主意,特别是当您试图强制执行新契约时

我建议您重新设计类,使其具有HashSet字段,而不是扩展HashSet

阅读第16项:偏爱组合而不是继承。

继承hashset的
addAll()
方法
类第一集currentSize=3,带有
currentSize+=e.size()指令。然后
super.addAll(e)调用
add(e)
方法三次。对于动态绑定,首先调用类
InheritHashSet
public boolean add(整数e)
,然后将
currentSize
增加到6

因此,您应该以以下方式实现
addAll
方法:

@Override
public boolean addAll(Collection<? extends Integer> e) {
    return super.addAll(e);
}
@覆盖

公共布尔addAll(CollectionWhat's
super.addAll(e)
do?这正是为什么不应该扩展HashSet,而应该使用HashSet。请注意,currentSize的名称非常糟糕。它根本不是大小。如果是,它将毫无用处,因为HashSet已经有了大小。@jbnize我不知道可以使用HashSet的
size()来确定大小
方法,我只是想知道为什么这种计算集合中元素数量的方法不能得到正确的答案。请查看
super.addAll
的源代码。它可能在内部调用
add
。这就是为什么会重复计算。如果扩展现有实现,则必须查看该实现如何直到HashSet决定不再调用add(),而是通过委托给新的私有doAdd()来实现addAll()方法,这将破坏子类并导致0而不是3。您不应该扩展HashSet。我完全同意,您指出这一点是正确的,但我们不知道OP代码的真正意图。他编写此代码可能只是为了一个简单的测试或研究。他只问为什么会出现这种奇怪的行为,事实并非如此立即意识到。是我忽略了什么,还是这个实现没有用?它只是调用
超级
方法,而不改变可见性,那么这有什么意义呢?当然,JB Nizet是对的。这很难。是“最干净”还是“最安全”解决方案可能是使用所需集合(
HashSet
)实现其
size
iterator
add
方法的
MySpecialSet extends AbstractSet implements Set
)但是我敢打赌,对于询问者真正想要达到的目标,有更优雅的解决方案……我只是从addAll实现中删除了
currentSize
增量,因为我注意到这是一个错误。你不知道该方法是否做了其他事情以及OP simplifi编辑它是因为他想专注于
currentSize
问题(并且为了创建一个最小的工作示例)。@Sotirios是的,你编辑它是对的。无论如何,我很快就会删除这一行
@Override
public boolean addAll(Collection<? extends Integer> e) {
    return super.addAll(e);
}