До сих пор я использовал оператор == в своей программе для сравнения всех моих строк. Однако я столкнулся с ошибкой, заменил одну из них на .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
Хотя == может использоваться для сравнения ссылок типа String, такой тест на равенство определяет, относятся ли два операнда к одному и тому же String объекту. Результатом будет, false если операнды являются разными String объектами, даже если они содержат одну и ту же последовательность символов (§ 3.10.5, §3.10.6). Содержимое двух строк s и t может быть проверено на равенство с помощью вызова метода s.equals(t).
Вы почти всегда хотите использовать Objects.equals(). В редкой ситуации, когда вы знаете, что имеете дело с интернированными строками, вы можете использовать ==.
Более того, строковый литерал всегда ссылается на один и тот же экземпляр класса String. Это связано с тем, что строковые литералы - или, в более общем смысле, строки, являющиеся значениями постоянных выражений (§ 15.28) - "интернированы", чтобы совместно использовать уникальные экземпляры с использованием метода String.intern.
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() из нулевой строки вызовет исключение:
Это связано с тем, что при создании любого строкового литерала 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 в обоих случаях: