В JDK 1.6 можно ли заменить операцию String equals на ==?

Когда я изучаю исходный код некоторых продуктов с открытым исходным кодом, я нахожу такой код:

if (a=="cluser")

a — это строковая переменная. Можно ли заменить операцию String equals на ==?


person L.J.W    schedule 30.04.2011    source источник
comment
Нет, == по-прежнему означает равенство ссылок на объекты. Код, который вы читаете, неверен, если он пытается выполнить сравнение строк.   -  person wkl    schedule 30.04.2011
comment
часто сторонний код основан на интернированных строках, таких как lucene или некоторые парсеры xml. Если это так, то == можно использовать.   -  person MeBigFatGuy    schedule 30.04.2011
comment
... Я нахожу такой код... - Да. Во многих продуктах есть ошибки... как с открытым исходным кодом, так и с закрытым исходным кодом.   -  person Stephen C    schedule 30.04.2011
comment
Некоторым из нас нравится хвастаться, какие мы умные мошенники, и использовать == для строк в тех случаях, когда это безопасно. Это недостаток характера, но что поделаешь?   -  person Affe    schedule 30.04.2011


Ответы (5)


Вы должны почти никогда использовать == и почти всегда использовать equals(). Он будет работать только с ==, если обе строки ссылаются на один и тот же объект. В String есть метод intern() для возврата той же ссылки для заданного строкового значения. Строковые литералы неявно интернированы. Только если у вас есть очень веская причина, вы должны использовать == для сравнения строк, и даже в этом случае вам нужно быть очень осторожным.

Единственной хорошей причиной является производительность, и очень редко это будет иметь значение. Оптимизируйте только тогда, когда вы точно знаете, что вам это нужно. В противном случае обычно не стоит хлопот. Если вы просматриваете некоторый открытый исходный код, у них может быть случай, когда сравнение находится в очень узком цикле или вызывается очень часто, и оптимизация может помочь. Или он был просто преждевременно оптимизирован и, возможно, казался безопасным.

person WhiteFang34    schedule 30.04.2011

Вы можете использовать ==, если две строки интернированы. Строковые литералы определены как интернированные, поэтому, если я, скажем, назначу литерал «fred» переменной String и передам его в качестве параметра методу в другом классе, где он сравнивается с «fred», тест == будет истинный.

Так что образец кода не то чтобы дефектный, скорее всего так.

person Hot Licks    schedule 30.04.2011
comment
просто наверное так - это нельзя слишком сильно подчеркивать! - person Stephen C; 30.04.2011

только если строки были «интернированы». Обычно нет.

person MJB    schedule 30.04.2011

Из Спецификации языка 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

Этот пример иллюстрирует шесть моментов:

  1. Литеральные строки в одном классе в одном пакете представляют собой ссылки на один и тот же объект String.
  2. Литеральные строки в разных классах одного и того же пакета представляют собой ссылки на один и тот же объект String.
  3. Литеральные строки в разных классах в разных пакетах также представляют собой ссылки на один и тот же объект String.
  4. Строки, вычисляемые константными выражениями, вычисляются во время компиляции, а затем обрабатываются как литералы.
  5. Строки, вычисляемые конкатенацией во время выполнения, создаются заново и, следовательно, различны.
  6. Результатом явного интернирования вычисляемой строки является та же строка, что и в любой ранее существовавшей литеральной строке с тем же содержимым.
person Edwin Dalorzo    schedule 30.04.2011

Оператор == проверяет, являются ли два объекта одним и тем же объектом. Он не сравнивает то, что находится в строках.

person Richard Brightwell    schedule 30.04.2011