В scaladoc scala.Any объясняется оператор == (или метод ==):
Выражение
x == thatэквивалентноif (x eq null) that eq null else x.equals(that)http://www.scala-lang.org/api/current/#scala.Any
Для объектов подклассов AnyRef я могу легко это понять, и я не видел никаких странных вещей.
Однако для значений AnyVal (я имею в виду Int, Double, Long и т.д.) указанное выше определение несколько сложно (1 eq null? Это не скомпилируется, если мы это делаем не конвертировать 1 в java.lang.Integer). Кроме того, == и equals() ведут себя по-разному.
Я приведу несколько примеров.
scala> 1 == 1 res0: Boolean = true scala> 1 == 1.0 res1: Boolean = true scala> 1 == 1.2 res2: Boolean = false scala> 2 == BigInt(2) res3: Boolean = true scala> 2.0 == BigInt(2) res4: Boolean = true scala> 2 == BigInt(3) res5: Boolean = false
Пока ничего странного. Но если мы делаем то же самое с методами equals(),
scala> 1 equals 1 res7: Boolean = true scala> 1 equals 1.0 res8: Boolean = false scala> 1 equals 1.2 res9: Boolean = false scala> 2 equals BigInt(2) res10: Boolean = false scala> 2.0 equals BigInt(2) res11: Boolean = false scala> 2 equals BigInt(3) res12: Boolean = false
Итак, если типы различны, equals() всегда возвращает false, тогда как == тесты, если они представляют одно и то же значение, если они преобразуются в один и тот же тип.
В случае подкласса AnyRef методы == и equals() возвращают то же самое.
scala> BigInt(2) == 2 res25: Boolean = true scala> BigInt(2) == 2.0 res26: Boolean = true scala> BigInt(3) == 2 res27: Boolean = false scala> BigInt(2) equals 2 res28: Boolean = true scala> BigInt(2) equals 2.0 res29: Boolean = true scala> BigInt(3) equals 2 res30: Boolean = false
Итак, почему методы == и equals() различаются для AnyVal?
Я использую Scala версию 2.10.2 (Java-сервер HotSpot (TM) 64-Bit Server, Java 1.7.0_25).
РЕДАКТИРОВАТЬ 1
Я видел, что == не может быть переопределен напрямую, поскольку он определен как окончательный метод в классе Any в соответствии с Программирование в Scala, 2nd Edition.
РЕДАКТИРОВАТЬ 2
Хотя есть ответ, мой вопрос остается. Я оставлю этот вопрос открытым.
Что соответствует scala.Int и scala.Long в Java, являются примитивными типами Java Int и Long.
В Java java.lang.Integer и java.lang.Long являются классами, поэтому их переменными являются ссылки, которые могут иметь null.
Это означает, что они как AnyRef в Scala. Не AnyVal.
Scala AnyVal - scala.Int и scala.Long не могут иметь значения null, ни Java Int, ни Long.
Кроме того, java.lang.Integer == в Java для ссылочного равенства (то же, что и eq в Scala).
То, что вы используете с помощью java.lang.Integer в Scala REPL, будет сильно отличаться от того, что вы получите с ним в чистом Java-проекте с исходным файлом .java в этом отношении.
Однако то, что я мог получить от использования классов примитивных типов в Java, было: (ЭТО ЯВЛЯЕТ)
class Main {
public static void main(String[] args) {
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1L)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(1.0)));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Integer(1))));
System.out.println(String.valueOf(new java.lang.Integer(1).equals(new java.lang.Long(1))));
}
}
Выход:
true false false true falseДа, они ведут себя подобно Scala AnyVal
equals(). Но почему тогда это происходит?
Соответствует ли Scala AnyVal == == примитивного типа Java
и Scala AnyVal equals() соответствует equals() типов классов Java?
Что относительно тестов на равенство с BigInt? В Java нет соответствующего примитивного типа.
Вопрос остается...
РЕДАКТИРОВАТЬ 3
Я мог бы найти некоторую информацию от scaladoc. (http://www.scala-lang.org/api/current/index.html#scala.Int)
Неявная информация из элемента теневых неявных членов,
Я мог найти == был перегружен для Char, Short, Float и...,
и == вызовет неявные преобразования int2double, int2float или int2long.
В то время как equals() определяется только для Any, и он будет вызывать неявное преобразование int2Integer.
То есть Int.equals() будет таким же, как java.lang.Integer.equals().
Остается один вопрос:
Почему == of AnyVal перегружен, а equals() of AnyVal не перегружен?