В 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
не перегружен?