Является ли метод Java assertEquals надежным?
Вопрос
Я знаю, что у ==
есть некоторые проблемы при сравнении двух строк
. Кажется, что String.equals ()
- лучший подход. Ну, я провожу тестирование JUnit, и я склонен использовать assertEquals (str1, str2)
. Это надежный способ утверждать, что две строки содержат одинаковое содержимое? Я бы использовал assertTrue (str1.equals (str2))
, но тогда у вас не будет возможности увидеть ожидаемые и фактические значения при сбое.
В связанной заметке есть ли у кого-нибудь ссылка на страницу или поток, в котором четко объясняются проблемы с str1 == str2
?
Решение
Вы должны всегда использовать .equals ()
при сравнении Strings
в Java.
JUnit вызывает метод .equals ()
для определения равенства в методе assertEquals (объект o1, объект o2)
.
Итак, вы определенно в безопасности, используя assertEquals (string1, string2)
. (Поскольку String
являются Object
s)
Вот ссылка на замечательный вопрос Stackoverflow относительно некоторых различий между ==
и .equals ()
.
Другие советы
assertEquals
использует метод равно
для сравнения. Существует другое утверждение assertSame
, в котором используется оператор ==
.
Чтобы понять, почему ==
не следует использовать со строками, необходимо понять, что делает ==
: он проверяет идентичность. То есть a == b
проверяет, ссылаются ли a
и b
на один и тот же объект . Он встроен в язык, и его поведение не может быть изменено различными классами. С другой стороны, метод equals
может быть переопределен классами. Хотя его поведение по умолчанию (в классе Object
) заключается в проверке идентичности с использованием оператора ==
, многие классы, включая String
, переопределяют вместо этого он должен сделать «эквивалентность»; проверять. В случае String
вместо проверки того, ссылаются ли a
и b
на один и тот же объект, a.equals (b)
проверяет, являются ли объекты, на которые они ссылаются, строками, которые содержат абсолютно одинаковые символы.
Время аналогии: представьте, что каждый объект String
- это лист бумаги, на котором что-то написано. Допустим, у меня есть два листа бумаги с "Foo" на них написано и еще одно с "Баром" написано на нем. Если я возьму первые два листа бумаги и воспользуюсь ==
для их сравнения, то вернусь false
, потому что по сути спрашивает "это один и тот же лист бумаги?" , Не нужно даже смотреть на то, что написано на бумаге. Тот факт, что я даю ему два листа бумаги (а не один и тот же дважды), означает, что он вернет false
. Однако, если я использую equals
, метод equals
прочитает две бумажки и увидит, что они говорят одно и то же (" Foo "), и поэтому вернем true
.
Ситуация, которая путается со строками, заключается в том, что в Java есть концепция «интернирования»; Строки, и это (эффективно) автоматически выполняется для любых строковых литералов в вашем коде. Это означает, что если в вашем коде есть два эквивалентных строковых литерала (даже если они находятся в разных классах), они на самом деле оба будут ссылаться на один и тот же объект String
. Это заставляет оператор ==
возвращать true
чаще, чем можно было ожидать.
В двух словах - у вас может быть два объекта String, которые содержат одинаковые символы, но являются разными объектами (в разных местах памяти). Оператор == проверяет, что две ссылки указывают на один и тот же объект (область памяти), но метод equals () проверяет, совпадают ли символы.
Обычно вас интересует проверка того, содержат ли две строки одинаковые символы, а не указывают ли они на одну и ту же ячейку памяти.
Да, он все время используется для тестирования. Весьма вероятно, что среда тестирования использует .equals () для таких сравнений.
Ниже приведена ссылка, объясняющая «ошибку равенства строк». По сути, строки в Java являются объектами, и когда вы сравниваете равенство объектов, обычно они сравниваются по адресу памяти, а не по содержимому. Из-за этого две строки не будут занимать один и тот же адрес, даже если их содержимое идентично, поэтому они не будут соответствовать друг другу, даже если при печати они выглядят одинаково.
http: //blog.enrii. ком / 2006/03/15 / Java-строка-равенство-синфазного ошибка /
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
JUnit assertEquals (obj1, obj2)
действительно вызывает obj1.equals (obj2)
.
Существует также assertSame (obj1, obj2)
, который выполняет obj1 == obj2
(т. е. проверяет, что obj1
и obj2
ссылается на тот же экземпляр ), чего вы пытаетесь избежать.
Значит, ты в порядке.
" Оператор
==
проверяет, являются ли дваОбъекта
одинаковымиObject
. "
http://leepoint.net/notes-java/data/strings /12stringcomparison.html р>
String
является объектом
в Java, поэтому он попадает в эту категорию правил сравнения.