Вот источник от 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 , это имеет много примеров, подобных этому.
Вообще говоря, хотя этого строго не выражают в контракте для , равняется () , объекты не должны считать себя равными другому объекту, который не имеет того же самого класса (даже если это - подкласс). Рассмотрите симметричное свойство - если a.equals (b) верен, то b.equals (a) должен также быть верным.
Позволяют нам иметь два объекта, foo
из класса Super
и bar
из класса Sub
, который расширяется Super
. Теперь рассмотрите реализацию equals()
в Супер, конкретно когда это назовут как foo.equals(bar)
. Нечто только знает, что панель со строгим контролем типов как Object
, так для получения точного сравнения, это должно проверить, что это - экземпляр Супер и если не возвращают false. Это, таким образом, эта часть прекрасна. Это теперь сравнивает все поля экземпляра, и т.д. (или независимо от того, что фактическая реализация сравнения), и находит их равными. Пока неплохо.
Однако согласно контракту это может только возвратить true, если это знает, что bar.equals (нечто) собирается возвратить true также. Так как панель может быть любым подклассом Супер, не ясно, будет ли равняние () метод переопределенным (и если, вероятно, будет). Таким образом, чтобы быть уверенными, что Ваша реализация корректна, необходимо записать его симметрично и удостовериться, что два объекта являются тем же классом.
более существенно, объекты различных классов нельзя действительно считать равными - так как в этом случае, только один из них может быть вставлен в HashSet<Sub>
, например.
Да, но все это сводится к выдерживающему сравнение алгоритму и как далеко взять преобразования. Например, что Вы хотите произойти, когда Вы пробуете m.Contains("5")
? Или если Вы передаете его массив с 5 как первый элемент? Просто разговор, это, кажется, обеспечено электричеством, "если типы отличаются, ключи отличаются".
Тогда берут набор с object
как ключ. Что Вы хотите произойти если Вы put
5L
, затем попытайтесь добраться 5
, "5"
...? Что, если Вы put
5L
и 5
и "5"
и Вы хотите проверить на 5F
?
, Так как это - универсальный набор (или шаблонный, или независимо от того, что Вы хотите назвать его), это должно было бы проверить и сделать некоторое специальное сравнение для определенных типов значения. Если K int
тогда проверка, если объект передал, long
, short
, float
, double
..., то преобразуйте и сравните. Если K float
тогда проверка, если объект передал...
Вы понимаете.
Другая реализация, возможно, была должна выдать исключение, если типы не соответствовали, однако, и мне часто жаль, что она не сделала.
Ваш вопрос кажется разумным на своей поверхности, но это было бы нарушение общих соглашений для, равняется (), если не его контракт, для возвращения true для двух различных типов.
Часть дизайна языка Java была для Объектов к никогда, неявно преобразовывают в другие типы, в отличие от C++. Это было частью создания Java маленький, простой язык. Разумная часть сложности C++ прибывает из неявных преобразований и их взаимодействий с другими функциями.
кроме того, Java имеет резкую и видимую дихотомию между примитивами и объектами. Это отличается от других языков, где это различие скрыто под покрытиями как оптимизация. Это означает, что Вы не можете ожидать, что Long и Integer будут действовать как длинный и международное
, код Библиотеки может быть записан для сокрытия этих различий, но это может на самом деле причинить вред путем создания среды программирования менее последовательной.
Таким образом, Вы кодируете, должен быть....
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
, Таким образом, часть Вашей проблемы является автоупаковкой. Другая часть - то, что у Вас есть различные типы, как другие плакаты указали.