assertEquals
использует метод equals
для сравнения. Существует другое утверждение, assertSame
, в котором используется оператор ==
.
Чтобы понять, почему ==
не следует использовать со строками, вам необходимо понять, что делает ==
: он выполняет проверку личности. То есть a == b
проверяет, относятся ли a
и b
к одному и тому же объекту . Он встроен в язык, и его поведение не может быть изменено различными классами. Метод equals
, с другой стороны, может быть переопределен классами. Хотя его поведение по умолчанию (в классе Object
) заключается в проверке идентичности с использованием оператора ==
, многие классы, включая String
, переопределяют его, вместо этого выполняя проверку "эквивалентности". В случае String
вместо проверки того, ссылаются ли a
и b
на один и тот же объект, a.equals(b)
проверяет, являются ли объекты, на которые они ссылаются, строками, которые содержат абсолютно одинаковые символы.
Время аналогии: представьте, что каждый String
объект - это лист бумаги с чем-то написанным на нем. Допустим, у меня есть два листа бумаги с надписью «Foo» и еще один с надписью «Bar». Если я возьму первые два листа бумаги и использую ==
, чтобы сравнить их, он вернет false
, потому что он по сути спрашивает: «Это один и тот же лист бумаги?». Не нужно даже смотреть на то, что написано на бумаге. Тот факт, что я даю ему два листа бумаги (а не один и тот же дважды), означает, что он вернет false
. Однако, если я использую equals
, метод equals
прочитает два листа бумаги и увидит, что они говорят одно и то же («Foo»), и поэтому вернет true
.
Ситуация, которая путает со строками, заключается в том, что в Java есть концепция "интернирования" строк, и это (эффективно) автоматически выполняется для любых строковых литералов в вашем коде. Это означает, что если в вашем коде есть два эквивалентных строковых литерала (даже если они находятся в разных классах), они на самом деле оба ссылаются на один и тот же объект String
. Это делает оператор ==
возвращающим true
чаще, чем можно было бы ожидать.