Почему Long.valueOf (0) .equals (Integer.valueOf (0)) ложь?

16
задан 2 revs 23 May 2017 в 12:08
поделиться

6 ответов

Вот источник от Long.java

public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

, Т.е. это должен быть тип Long, чтобы быть равным. Я думаю основное отличие между:

long l = 42L
int i = 42;
l == i

и Ваш пример выше то, что с примитивами неявное расширение международного значения может произойти, однако с типами объектов нет никаких правил для того, чтобы неявно преобразовать от Целого числа до Long.

Также выезд Трудные вопросы Java , это имеет много примеров, подобных этому.

24
ответ дан 30 November 2019 в 16:30
поделиться

Вообще говоря, хотя этого строго не выражают в контракте для , равняется () , объекты не должны считать себя равными другому объекту, который не имеет того же самого класса (даже если это - подкласс). Рассмотрите симметричное свойство - если a.equals (b) верен, то b.equals (a) должен также быть верным.

Позволяют нам иметь два объекта, foo из класса Super и bar из класса Sub, который расширяется Super. Теперь рассмотрите реализацию equals() в Супер, конкретно когда это назовут как foo.equals(bar). Нечто только знает, что панель со строгим контролем типов как Object, так для получения точного сравнения, это должно проверить, что это - экземпляр Супер и если не возвращают false. Это, таким образом, эта часть прекрасна. Это теперь сравнивает все поля экземпляра, и т.д. (или независимо от того, что фактическая реализация сравнения), и находит их равными. Пока неплохо.

Однако согласно контракту это может только возвратить true, если это знает, что bar.equals (нечто) собирается возвратить true также. Так как панель может быть любым подклассом Супер, не ясно, будет ли равняние () метод переопределенным (и если, вероятно, будет). Таким образом, чтобы быть уверенными, что Ваша реализация корректна, необходимо записать его симметрично и удостовериться, что два объекта являются тем же классом.

более существенно, объекты различных классов нельзя действительно считать равными - так как в этом случае, только один из них может быть вставлен в HashSet<Sub>, например.

6
ответ дан 30 November 2019 в 16:30
поделиться

Да, но все это сводится к выдерживающему сравнение алгоритму и как далеко взять преобразования. Например, что Вы хотите произойти, когда Вы пробуете m.Contains("5")? Или если Вы передаете его массив с 5 как первый элемент? Просто разговор, это, кажется, обеспечено электричеством, "если типы отличаются, ключи отличаются".

Тогда берут набор с object как ключ. Что Вы хотите произойти если Вы put 5L, затем попытайтесь добраться 5, "5"...? Что, если Вы put 5L и 5 и "5" и Вы хотите проверить на 5F?

, Так как это - универсальный набор (или шаблонный, или независимо от того, что Вы хотите назвать его), это должно было бы проверить и сделать некоторое специальное сравнение для определенных типов значения. Если K int тогда проверка, если объект передал, long, short, float, double..., то преобразуйте и сравните. Если K float тогда проверка, если объект передал...

Вы понимаете.

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

5
ответ дан 30 November 2019 в 16:30
поделиться

Ваш вопрос кажется разумным на своей поверхности, но это было бы нарушение общих соглашений для, равняется (), если не его контракт, для возвращения true для двух различных типов.

4
ответ дан 30 November 2019 в 16:30
поделиться

Часть дизайна языка Java была для Объектов к никогда, неявно преобразовывают в другие типы, в отличие от C++. Это было частью создания Java маленький, простой язык. Разумная часть сложности C++ прибывает из неявных преобразований и их взаимодействий с другими функциями.

кроме того, Java имеет резкую и видимую дихотомию между примитивами и объектами. Это отличается от других языков, где это различие скрыто под покрытиями как оптимизация. Это означает, что Вы не можете ожидать, что Long и Integer будут действовать как длинный и международное

, код Библиотеки может быть записан для сокрытия этих различий, но это может на самом деле причинить вред путем создания среды программирования менее последовательной.

0
ответ дан 30 November 2019 в 16:30
поделиться

Таким образом, Вы кодируете, должен быть....

java.util.HashMap<Long, String> m = new java.util.HashMap<Long, String>();
m.put(5L, "Five"); // compiler barfs on m.put(5, "Five")
System.out.println(m.containsKey(5L)); // true

Вы забываете, что Java автоупаковывает Ваш код, таким образом, вышеупомянутый код был бы equivelenet к

java.util.HashMap<Long, String> m = new java.util.HashMap<Long, String>();
m.put(new Long(5L), "Five"); // compiler barfs on m.put(5, "Five")
System.out.println(m.containsKey(new Long(5))); // true
System.out.println(m.containsKey(new Long(5L))); // true

, Таким образом, часть Вашей проблемы является автоупаковкой. Другая часть - то, что у Вас есть различные типы, как другие плакаты указали.

0
ответ дан 30 November 2019 в 16:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: