В чем разница между == и.равные в скале?



В чем разница между == и .equals() в Scala, и когда какую использовать?



является ли реализация такой же, как в Java?



EDIT: связанный с этим вопрос говорит о конкретных случаях AnyVal. Более общий случай Any.

517   5  

5 ответов:

вы обычно используете ==, Он направляет к equals, за исключением того, что он лечит nulls правильно. Равенство ссылок (редко используется) -eq.

== является окончательным методом и вызывает .equals, которое не является окончательным.

это радикально отличается от Java, где == является оператором, а не методом и строго сравнивает ссылочное равенство для объектов.

TL; DR

  • переопределить equals метод для сравнения содержимого каждого экземпляра. Это то же самое equals метод, используемый в Java
  • использовать == оператор для сравнения, не беспокоясь о null ссылки
  • использовать eq метод, чтобы проверить, если оба аргумента являются ровно та же ссылка. Не рекомендуется использовать, если вы не понимаете, как это работает и часто equals будет работать для того, что вам нужно вместо этого. И убедитесь в этом используйте это только с AnyRef аргументы, а не просто Any

Примечание: На случай equals, как и в Java, он может не возвращать тот же результат, если вы переключаете аргументы, например 1.equals(BigInt(1)) вернутся false где обратное возвратится true. Это связано с тем, что каждая реализация проверяет только определенные типы. Примитивные числа не проверяют, является ли второй аргумент Number, ни BigInt типы, но только другие примитивные типы

подробности

The AnyRef.equals(Any) метод-это тот, который переопределяется подклассами. Метод из спецификации Java, который также перешел на Scala. Если используется на распакованном экземпляре, он помещается в коробку, чтобы вызвать это (хотя скрыто в Scala; более очевидно в Java с int ->Integer). Реализация по умолчанию просто сравнивает ссылки (как в Java)

The Any.==(Any) метод сравнивает два объекта и позволяет любому аргументу быть null (как будто вызывая a статический метод с двумя экземплярами). Он сравнивает, если оба null, затем он вызывает equals(Any) метод экземпляра в упаковке.

The AnyRef.eq(AnyRef) метод сравнивает только ссылки, то есть, где экземпляр находится в памяти. Для этого метода нет неявного бокса.

примеры

  • 1 equals 2 вернутся false, так как он перенаправляет на Integer.equals(...)
  • 1 == 2 вернутся false, так как он перенаправляет на Integer.equals(...)
  • 1 eq 2 не будет компилироваться, так как для этого требуются оба аргумента типа AnyRef
  • new ArrayList() equals new ArrayList() вернутся true, так как он проверяет содержимое
  • new ArrayList() == new ArrayList() вернутся true, так как он перенаправляет на equals(...)
  • new ArrayList() eq new ArrayList() вернутся false, как оба аргумента являются разными экземплярами
  • foo equals foo вернутся true, если foo и null, затем бросит NullPointerException
  • foo == foo вернутся true, даже если foo и null
  • foo eq foo вернутся true, так как оба аргумента ссылаются на одну и ту же ссылку

есть интересная разница между == и equals на Float и Double типы: они относятся к NaN иначе:

scala> Double.NaN == Double.NaN
res3: Boolean = false

scala> Double.NaN equals Double.NaN
res4: Boolean = true

Edit: как было указано в комментарии - "это также происходит в Java" - зависит от того, что именно этой - это:

public static void main(final String... args) {
    final double unboxedNaN = Double.NaN;
    final Double boxedNaN = Double.valueOf(Double.NaN);

    System.out.println(unboxedNaN == unboxedNaN);
    System.out.println(boxedNaN == boxedNaN);
    System.out.println(boxedNaN.equals(boxedNaN));
}

выводит

false
true
true

Итак,unboxedNan доходность false при сравнении для равенства, потому что именно так определяют числа с плавающей запятой IEEE это и должно действительно происходить в каждом языке программирования (хотя это как-то путает с понятием идентичности).

коробочный NaN дает true для сравнения с использованием == в Java, как мы сравниваем ссылки на объекты.

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

в переводе на Scala вопрос немного сложнее, чем Scala объединил примитивные и объектные типы в Any и переводится в примитивный двойной и коробочный двойной по мере необходимости. Таким образом, скала == видимо, сводится к сравнению примитивных NaN значения а equals использует тот, который определен на коробочных двойных значениях (существует много неявной магии преобразования, и есть вещи, которые сводятся на двойники RichDouble).

если вам действительно нужно узнать, если что-то на самом деле NaN использовать isNaN:

В Scala == сначала проверить Null значения, а затем называет равна метод на первом объекте

Comments

    Ничего не найдено.