I wasn't sure on how to ask this question. But, what is the different between these 2 lines of code?
Set<Integer> a = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
a.add(i);
a.remove(i - 1);
}
System.out.println(a.size());
I expected 99 to be the output
Output is 1
Set<Short> a = new HashSet<Short>();
for (Short i = 0; i < 100; i++) {
a.add(i);
a.remove(i - 1);
}
System.out.println(a.size());
I expected 99 to be the output
Output is 100
The type of the expression i - 1
is int
because all operands in an integer arithmetic expression are widened to at least int
. Set<Short>
has add(Short)
and remove(Object)
so there's no casting/autoboxing needed on the remove
call. Therefore you are trying to remove Integer
s from a set of Short
s.
Note that for this reason it almost never makes sense to declare a Set<Number>
:
final Set<Number> ns = new HashSet<>();
final short s = 1;
ns.add(s);
ns.add(s+0);
ns.add(s+0L);
System.out.println(ns); // prints [1, 1, 1]
As a bonus round, if you change the set implementation to TreeSet
, the magic disappears and it throws a ClassCastException
, giving away the trick.
Deep down, this issue has to do with the fact that equality is a symmetric relation, which must not distinguish the right hand side from the left hand side. These semantics are impossible to achieve with Java's single-dispatch methods.