Я согласен, что результат этой программы действительно озадачивает :
import java.util.*;
class Item {
@Override
public boolean equals(Object obj) {
return false; // not even equal to itself.
}
}
class Test {
public static void main(String[] args) {
Collection<Item> items = new HashSet<Item>();
Item i = new Item();
items.add(i);
System.out.println(items.contains(i)); // Prints true!
}
}
Ответ заключается в том, что реализация contains
проверяет argument == object
перед выполнением argument.equals(object)
.Результат от contains
равен true
, поскольку item == item
выполняется, даже если item.equals(item)
возвращает false.
Предполагая, что equals
следует своему контракту (является рефлексивным), таким образомреализация contains
правильна.
Если вы внимательно прочитали цитату, которую вы разместили, автор включает в себя слово " почти " :) Кажетсявы наткнулись на одно из немногих исключений из правила.
Другие коллекции (например, ArrayList
) используют equals
напрямую, и если вы измените с new HashSet<Item>()
на new ArrayList<Item>()
ввышеуказанная программа печатает false
, как и ожидалось.