Является ли метод Java assertEquals надежным?
Я знаю, что ==
имеет некоторые проблемы при сравнении двух Strings
. Кажется, что String.equals()
- лучший подход. Ну, я тестирую JUnit, и я склонен использовать assertEquals(str1, str2)
. Это надежный способ утверждать, что две строки содержат один и тот же контент? Я использовал бы assertTrue(str1.equals(str2))
, но тогда вы не получите преимущества, чтобы увидеть, что ожидаемые и фактические значения находятся в состоянии сбоя.
В какой-либо заметке кто-нибудь имеет ссылку на страницу или поток, которые явно объясняют проблемы с str1 == str2
?
Ответы
Ответ 1
Вы должны всегда использовать .equals()
при сравнении Strings
в Java.
JUnit вызывает метод .equals()
для определения равенства в методе assertEquals(Object o1, Object o2)
.
Итак, вы определенно безопасны, используя assertEquals(string1, string2)
. (Потому что String
Object
s)
fooobar.com/questions/37055/... относительно некоторых различий между ==
и .equals()
.
Ответ 2
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
чаще, чем можно было бы ожидать.
Ответ 3
В двух словах - вы можете иметь два объекта String, которые содержат одни и те же символы, но разные объекты (в разных ячейках памяти). Оператор == проверяет, что две ссылки указывают на один и тот же объект (ячейка памяти), но метод equals() проверяет, совпадают ли символы.
Обычно вы заинтересованы в том, чтобы проверить, содержат ли две строки одни и те же символы, а не указывают ли они на одну и ту же ячейку памяти.
Ответ 4
Да, он используется все время для тестирования. Весьма вероятно, что в рамках тестирования используется .equals() для таких сравнений.
Ниже приведена ссылка, объясняющая "ошибку равенства строк". По сути, строки в Java являются объектами, и когда вы сравниваете равенство объектов, их обычно сравнивают по адресу памяти, а не по контенту. Из-за этого две строки не будут занимать один и тот же адрес, даже если их содержимое идентично, поэтому они не будут корректно совпадать, даже если они выглядят одинаково при печати.
http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/
Ответ 5
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);
}
}
Ответ 6
JUnit assertEquals(obj1, obj2)
действительно вызывает obj1.equals(obj2)
.
Там также assertSame(obj1, obj2)
, который делает obj1 == obj2
(то есть проверяет, что obj1
и obj2
ссылаются на один и тот же экземпляр), чего вы пытаетесь избежать.
Итак, ты в порядке.
Ответ 7
"Оператор ==
проверяет, являются ли два Objects
точно такими же Object
."
http://leepoint.net/notes-java/data/strings/12stringcomparison.html
String
является Object
в java, поэтому он попадает в эту категорию правил сравнения.