Когда “” == s является ложью, но “” .equals (s) верен

Можно разбить сценарии в отдельные файлы для разработки, затем создать версию "выпуска", где Вы переполняете их всех вместе и работаете Компрессор YUI или что-то подобное на ней.

33
задан Bill the Lizard 30 July 2012 в 03:56
поделиться

10 ответов

String s = "";
String s2 = someUserInputVariale.toLowercase(); // where the user entered in ""

Что-то вроде этого может привести к тому, что s == s2 будет оцениваться как false.

Большое количество кода создает новые строки без раскрытия вызова new String () .

26
ответ дан 27 November 2019 в 18:03
поделиться

Если вы используете поиск по коду Google, вы можете найти множество мест, где люди совершают ту же ошибку: google для файла: .java \ = \ = \ \ "\ " Конечно, это может быть правильная идиома в тщательно контролируемых обстоятельствах, но обычно это просто ошибка.

0
ответ дан 27 November 2019 в 18:03
поделиться
"" == value // yields false

и

"".equals( value ) // yields true

каждый раз, когда значение переменной value не было интернировано. Так будет, если значение вычисляется во время выполнения. См. раздел JLS 3.10.5 Строковые литералы для примера кода, иллюстрирующего это:

Таким образом, тестовая программа, состоящая из модуля компиляции (§7.3):

 package testPackage;
class Test {
 public static void main (String [] args) {
 Строка hello = "Привет", lo = "lo";
 System.out.print ((привет == "Привет") + "");
 System.out.print ((Other.hello == привет) + "");
 System.out.print ((other.Other.hello == привет) + "");
 System.out.print ((привет == ("Хель" + "ло")) + "");
 System.out.print ((привет == ("Хель" + ло)) + "");
 System.out.println (привет == ("Hel" + lo) .intern ());
 }
}
class Other {static String hello = "Привет"; }

и блок компиляции:

 другой пакет;
открытый класс Другое {статическая строка hello = "Привет"; }

дает результат:

 true true true true false true

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

  • Литеральные строки в одном классе (§8) в одном пакете (§7) представляют ссылки на один и тот же объект String (§4.3.1).
  • Литеральные строки внутри разные классы в одном пакете представляют ссылки на один и тот же объект String.
  • Литеральные строки в разных классах в разных пакетах аналогичным образом представляют ссылки на один и тот же объект String.
  • Строки, вычисляемые с помощью константных выражений (§15.28), вычисляются при компиляции времени, а затем обрабатываются так, как если бы они были литералами.
  • Строки, вычисляемые во время выполнения, создаются заново и, следовательно, отличаются.
  • Результатом явного интернирования вычисленной строки является та же строка, что и любая ранее существующая буквальная строка с тем же содержание.
21
ответ дан 27 November 2019 в 18:03
поделиться

Если вы можете взять книгу Java Puzzlers Джошуа Блоха и Нила Гафтера и посмотреть на загадку 13 «Скотный двор» ... совет по этому поводу. Я собираюсь скопировать соответствующий текст:

«Вы, возможно, знаете, что константы времени компиляции типа String интернированы [JLS 15.28]. Другими словами, любые два константные выражения типа String , которые обозначают одну и ту же последовательность символов, представлены идентичными ссылками на объекты ... Ваш код редко, если вообще когда-либо, должен зависеть от интернирования строковых констант. Интернирование было разработано исключительно для уменьшения объема памяти виртуальной машины, а не как инструмент для программистов ... При сравнении ссылок на объекты,

10
ответ дан 27 November 2019 в 18:03
поделиться

Ожидаете ли вы, что «abcde» .substring (1,2) и «zbcdefgh» .substring (1,2) дадут то же самое Строковый объект?

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

Теперь рассмотрим, когда длина подстроки равна 0, подстрока (1, 1) . Это дает строку нулевой длины, но неудивительно, что «abcde» .substring (1,1) - это объект, отличный от «zbcdefgh» .substring (1,2) и, следовательно, по крайней мере один из них отличается от "".

7
ответ дан 27 November 2019 в 18:03
поделиться

Насколько я понимаю, при компиляции кода Java в байт-код или при запуске программы одни и те же строки будут ссылаться на один и тот же объект в большинстве случаев для экономии памяти. Так что иногда вам сходит с рук == сравнения строк. Но это оптимизация компилятора, на которую нельзя положиться.

Но иногда случается, что компилятор решает не выполнять эту оптимизацию или программа не может увидеть, что строки совпадают, и внезапно проверка не выполняется, поскольку вы полагаетесь на некоторую базовую оптимизацию вуду. это зависит от реализации используемого вами jvm и так далее.

Поэтому использование equals всегда полезно. Для пустых строк есть другие возможности, такие как сравнение с length == 0 или, если вас не волнует обратная совместимость, есть string.empty ().

3
ответ дан 27 November 2019 в 18:03
поделиться

Также приходилось иметь дело с пробелами в именах путей. В конечном итоге я использовал рекурсию и для элемента в / path / * :

2
ответ дан 27 November 2019 в 18:03
поделиться

Проверьте эту ссылку: http://mindprod.com/jgloss/string.html#COMPARISON в превосходном Canadian Mind Products Java & Internet Glossary ]. Стоит поставить закладку.

0
ответ дан 27 November 2019 в 18:03
поделиться

В javadoc для String.intern () есть хороший комментарий по == vs. .equals () .

В документации также уточняется, что каждый строковый литерал является intern 'd.

public String intern ()

Возвращает каноническое представление для строкового объекта.

] Пул строк, изначально пустой, поддерживается классом String.

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

Отсюда следует, что для любых двух строк s и t, s.intern () == t.intern () - это истина тогда и только тогда, когда s.equals (t) истина.

Все литеральные строки и строковые значения постоянные выражения интернированы. Строковые литералы определены в §3.10.5 спецификации языка Java

. Возвращает: строку с таким же содержимое как эта строка, но гарантированно из пула уникальных строки.

0
ответ дан 27 November 2019 в 18:03
поделиться

Почему бы не использовать:

if (value != null && value.length == 0) {
    // do stuff (above could be "== null ||"
}

Вы должны использовать equals () , потому что == для объектов сравнивает ссылки, т.е. являются ли они одним и тем же объектом. Хотя во время компиляции Java находит идентичные строки и заставляет их использовать одну и ту же ссылку (строки неизменяемы), во время выполнения легко создать пустые строки с разными ссылками, где == не выполняется для вашего типичного намерения equals () .

0
ответ дан 27 November 2019 в 18:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: