Нарушение правила рефлексивности при переопределении методом равных - PullRequest
4 голосов
/ 02 августа 2011

У меня есть сомнения из книги Efective Java.Сомнение касается метода равных
нарушение рефлексивного правила.В книге сказано следующее:

" Если вы нарушите его, а затем добавите экземпляр своего класса в коллекцию, метод содержимого коллекции почти наверняка скажет, что коллекция несодержит экземпляр, который вы только что добавили."

Для проверки я написал пример класса, но метод содержимого не возвращает false Он возвращает true.Кто-нибудь может сказать, в чем проблема?

Ответы [ 2 ]

6 голосов
/ 02 августа 2011

Я согласен, что результат этой программы действительно озадачивает :

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, как и ожидалось.

5 голосов
/ 02 августа 2011

Рефлексивное средство x.equals(x) должно вернуть true

class Foo {
   int i;
   public boolean equals(Object obj) {
      return ((Foo) obj).i < this.i;
   }
}

это вернет false.А когда вы помещаете его в список и вызываете list.contains(foo), он возвращает false, потому что ни один из элементов в списке не был равен тому, который вы передали.Это так, потому что list.contains(..) выполняет итерации элементов и для каждого из них проверяет if (elem.equals(arg))

См. Документы Collection.contains(..)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...