`class InstrumentedSet<E> extends HashSet<E> { int added = 0; @Override public boolean add(E e) { added++; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { added += c.size(); return super.addAll(c); } }` — calling `addAll(List.of("a", "b", "c"))` on a fresh instance leaves `added == 6`, not 3. Where do the extra three come from, and what does it say about extending a class you don't own?
HashSet.addAll is inherited from AbstractCollection, and its implementation happens to work by calling add() once for each element in the given collection — an internal detail of how addAll gets its job done, not part of its documented contract. Because add() is overridden in InstrumentedSet, and every call to it — including the ones addAll's own implementation makes internally — is a virtual call that dispatches to whichever add() the actual object's class provides, each of those three internal calls lands on InstrumentedSet's overridden add(), incrementing added three more times on top of the three addAll itself already added. The count for three elements ends up at six: three from addAll's own += c.size(), three more from add() firing three times underneath it. The lesson this example is famous for (it's Effective Java's own): whether one inherited method calls another is an implementation detail of a class you don't own, it can change release to release with no compile error and no test failure that only checks 'was a request timed/counted', and it's the concrete reason composition — wrapping a Set and forwarding to it explicitly — is usually the safer choice over extending one.