Как мне сравнить строки в Java?
До сих пор я использовал оператор ==
в своей программе для сравнения всех моих строк. Однако я столкнулся с ошибкой, заменил одну из них на .equals()
вместо этого, и это исправило ошибку.
Это ==
плохо? Когда это следует и не следует использовать? В чем разница?
Переведено автоматически
Ответ 1
==
проверяет равенство ссылок (являются ли они одним и тем же объектом).
.equals()
проверяет равенство значений (содержат ли они одни и те же данные).
Objects.equals() проверяет null
перед вызовом.equals()
, поэтому вам не нужно этого делать (доступно начиная с JDK7, также доступно в Guava).
Следовательно, если вы хотите проверить, имеют ли две строки одинаковое значение, вы, вероятно, захотите использовать Objects.equals()
.
// These two have the same value
new String("test").equals("test") // --> true
// ... but they are not the same object
new String("test") == "test" // --> false
// ... neither are these
new String("test") == new String("test") // --> false
// ... but these are because literals are interned by
// the compiler and thus refer to the same object
"test" == "test" // --> true
// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true
// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true
Из спецификации языка Java JLS 15.21.3. Ссылаются на операторы равенства ==
и !=
:
Хотя
==
может использоваться для сравнения ссылок типаString
, такой тест на равенство определяет, относятся ли два операнда к одному и тому жеString
объекту. Результатом будет,false
если операнды являются разнымиString
объектами, даже если они содержат одну и ту же последовательность символов (§ 3.10.5, §3.10.6). Содержимое двух строкs
иt
может быть проверено на равенство с помощью вызова методаs.equals(t)
.
Вы почти всегда хотите использовать Objects.equals()
. В редкой ситуации, когда вы знаете, что имеете дело с интернированными строками, вы можете использовать ==
.
Из JLS 3.10.5. Строковые литералы:
Более того, строковый литерал всегда ссылается на один и тот же экземпляр класса
String
. Это связано с тем, что строковые литералы - или, в более общем смысле, строки, являющиеся значениями постоянных выражений (§ 15.28) - "интернированы", чтобы совместно использовать уникальные экземпляры с использованием методаString.intern
.
Похожие примеры также можно найти в JLS 3.10.5-1.
Другие методы, которые следует рассмотреть
String.equalsIgnoreCase() значение равенства, игнорирующее регистр. Однако имейте в виду, что этот метод может привести к неожиданным результатам в различных случаях, связанных с локализацией, см. Этот вопрос .
String.contentEquals() сравнивает содержимое String
с содержимым любого CharSequence
(доступно начиная с Java 1.5). Избавляет вас от необходимости превращать ваш StringBuffer и т.д. В строку перед выполнением сравнения на равенство, но оставляет вам проверку null.
Ответ 2
==
проверяет ссылки на объекты, .equals()
проверяет строковые значения.
Иногда это выглядит так, как будто ==
сравнивает значения, потому что Java выполняет некоторые закулисные действия, чтобы убедиться, что идентичные встроенные строки на самом деле являются одним и тем же объектом.
Например:
String fooString1 = new String("foo");
String fooString2 = new String("foo");
// Evaluates to false
fooString1 == fooString2;
// Evaluates to true
fooString1.equals(fooString2);
// Evaluates to true, because Java uses the same object
"bar" == "bar";
Но остерегайтесь нулей!
==
отлично обрабатывает null
строки, но вызов .equals()
из нулевой строки вызовет исключение:
String nullString1 = null;
String nullString2 = null;
// Evaluates to true
System.out.print(nullString1 == nullString2);
// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));
Итак, если вы знаете, что fooString1
может быть null, сообщите об этом читателю, написав
System.out.print(fooString1 != null && fooString1.equals("bar"));
Следующие строки короче, но менее очевидно, что они проверяют наличие null:
System.out.print("bar".equals(fooString1)); // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar")); // Java 7 required
Ответ 3
==
сравнивает ссылки на объекты.
.equals()
сравнивает строковые значения.
Иногда ==
создается иллюзия сравнения строковых значений, как в следующих случаях:
String a="Test";
String b="Test";
if(a==b) ===> true
Это связано с тем, что при создании любого строкового литерала JVM сначала выполняет поиск этого литерала в пуле строк, и если находит совпадение, та же ссылка будет дана на новую строку. Из-за этого мы получаем:
(a ==b) ===> true
String Pool
b -----------------> "test" <-----------------a
Однако, ==
сбой в следующем случае:
String a="test";
String b=new String("test");
if (a==b) ===> false
В этом случае для new String("test")
инструкции в куче будет создана новая строка, и на нее будет дана ссылка b
, поэтому b
ссылка будет дана в куче, а не в пуле строк.
Теперь a
указывает на строку в пуле строк, в то время как b
указывает на строку в куче. Из-за этого мы получаем:
if(a==b) ===> false.
String Pool
"test" <-------------------- a
Heap
"test" <-------------------- b
В то время как .equals()
всегда сравнивает значение String, чтобы оно давало true в обоих случаях:
String a="Test";
String b="Test";
if(a.equals(b)) ===> true
String a="test";
String b=new String("test");
if(a.equals(b)) ===> true
Поэтому использование .equals()
всегда лучше.
Ответ 4
Оператор ==
проверяет, являются ли две строки в точности одним и тем же объектом.
Метод .equals()
проверит, имеют ли две строки одинаковое значение.