#java #string #equals
#java — язык #строка #равно
Вопрос:
Изучая исходный код некоторых продуктов с открытым исходным кодом, я нахожу код, подобный:
if (a=="cluser")
a
является строковой переменной. Можно ли заменить equals
операцию String на ==
?
Комментарии:
1. Нет,
==
по-прежнему означает равенство ссылок на объекты. Этот код, который вы читаете, неверен, если он пытается выполнить сравнение строк.2. часто код третьей части основан на интернированных строках, таких как lucene или некоторые анализаторы xml. Если это так, то == можно использовать.
3. «… Я нахожу код, подобный …» — Да. Во многих продуктах есть ошибки … как с открытым исходным кодом, так и с закрытым исходным кодом.
4. Некоторым из нас нравится хвастаться, какие мы умные педерасты, и использовать == для строк в тех случаях, когда это безопасно. Это недостаток символа, но что вы можете сделать?
Ответ №1:
Вы должны почти никогда не использовать ==
и почти всегда использовать equals()
. Это будет работать только с ==
, если обе строки ссылаются на один и тот же объект. Существует intern()
метод String
, возвращающий ту же ссылку для заданного строкового значения. Строковые литералы неявно интернированы. Только если у вас есть очень веская причина, вы должны использовать ==
для сравнения строк, и даже тогда вам нужно быть очень осторожным.
Единственная веская причина — производительность, и очень редко это будет иметь значение. Оптимизируйте только тогда, когда вы точно знаете, что вам это нужно сделать. В противном случае обычно это не стоит хлопот. Если вы просматриваете какой-либо открытый исходный код, у них может быть случай, когда сравнение выполняется в очень узком цикле или вызывается очень часто, и оптимизация может помочь. Или это было просто преждевременно оптимизировано и, возможно, казалось безопасным.
Ответ №2:
Вы можете использовать ==, если две строки интернированы. Строковые литералы определены как интернированные, поэтому, если я, скажем, присвою строковой переменной литерал «fred» и передам его в качестве параметра методу в другом классе, где он сравнивается с «fred», тест == будет истинным.
Таким образом, образец кода, безусловно, не является дефектным, просто, вероятно, это так.
Комментарии:
1. «просто, вероятно, так» — это нельзя подчеркивать слишком сильно!
Ответ №3:
только если строки были «интернированы». Обычно нет.
Ответ №4:
Из спецификации языка Java, раздел 3.10.5 Строковые литералы
Каждый строковый литерал является ссылкой на экземпляр класса String. Строковые объекты имеют постоянное значение. Строковые литералы — или, в более общем смысле, строки, являющиеся значениями постоянных выражений, «интернируются» таким образом, чтобы совместно использовать уникальные экземпляры, используя метод String.intern .
Таким образом, тестовая программа, состоящая из модуля компиляции:
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") " ");
System.out.print((Other.hello == hello) " ");
System.out.print((other.Other.hello == hello) " ");
System.out.print((hello == ("Hel" "lo")) " ");
System.out.print((hello == ("Hel" lo)) " ");
System.out.println(hello == ("Hel" lo).intern());
}
}
class Other { static String hello = "Hello"; }
и модуль компиляции:
package other;
public class Other { static String hello = "Hello"; }
выдает вывод:
true true true true false true
Этот пример иллюстрирует шесть пунктов:
- Литеральные строки в пределах одного класса в одном пакете представляют ссылки на один и тот же объект String.
- Литеральные строки внутри разных классов в одном пакете представляют ссылки на один и тот же объект String.
- Литеральные строки в разных классах в разных пакетах аналогично представляют ссылки на один и тот же объект String.
- Строки, вычисляемые с помощью постоянных выражений, вычисляются во время компиляции, а затем обрабатываются так, как если бы они были литералами.
- Строки, вычисляемые с помощью конкатенации во время выполнения, создаются заново и, следовательно, различны.
- Результатом явного интернирования вычисляемой строки является та же строка, что и любая ранее существовавшая строка литерала с тем же содержимым.
Ответ №5:
Оператор == проверяет, являются ли два объекта в точности одним и тем же объектом. Это не сравнивает то, что находится в строках.