[На момент написания этой статьи были опубликованы три других ответа.]
Повторюсь, цель моего вопроса - найти стандартные случаи тестов, чтобы подтвердить, что hashCode
и equals
согласуются друг с другом. Мой подход к этому вопросу состоит в том, чтобы представить общие пути, которые программисты выбирают при написании рассматриваемых классов, а именно неизменяемые данные. Например:
- Написал
equals()
без записи hashCode()
. Это часто означает, что равенство было определено как равенство полей двух экземпляров.
- Написал
hashCode()
без записи equals()
. Это может означать, что программист искал более эффективный алгоритм хеширования.
В случае №2 проблема кажется мне несуществующей. Никаких дополнительных экземпляров не было сделано equals()
, поэтому дополнительные экземпляры не должны иметь одинаковые хэш-коды. В худшем случае алгоритм хеширования может дать худшую производительность для хеш-карт, что выходит за рамки этого вопроса.
В случае # 1 стандартный модульный тест влечет за собой создание двух экземпляров одного и того же объекта с одинаковыми данными, передаваемыми в конструктор, и проверку одинаковых хеш-кодов. Как насчет ложных срабатываний? Можно выбрать параметры конструктора, которые просто дают одинаковые хеш-коды для все же ненадежного алгоритма. Модульный тест, который стремится избежать таких параметров, будет соответствовать духу этого вопроса. Сочетание здесь заключается в том, чтобы проверить исходный код equals()
, тщательно продумать и написать тест на его основе, но, хотя это может быть необходимо в некоторых случаях, могут также быть общие тесты, которые обнаруживают общие проблемы - и такие тесты также выполнить дух этого вопроса.
Например, если тестируемый класс (назовите его Data) имеет конструктор, который принимает строку, и экземпляры, построенные из строк, которые equals()
дают экземпляры, которые были equals()
, тогда хороший тест, вероятно, будет проверять :
new Data("foo")
- еще
new Data("foo")
Мы могли бы даже проверить хеш-код для new Data(new String("foo"))
, чтобы заставить строку не интернироваться, хотя, скорее всего, будет получен правильный хеш-код, чем Data.equals()
, по моему мнению, правильный результат.
Ответ Эли Кортрайта - пример тщательного осмысления способа взлома алгоритма хеширования, основанного на знании спецификации equals
. Пример специальной коллекции - хороший пример, так как пользовательские Collection
иногда появляются, и они довольно склонны к взлому в алгоритме хеширования.