Можно разбить сценарии в отдельные файлы для разработки, затем создать версию "выпуска", где Вы переполняете их всех вместе и работаете Компрессор YUI или что-то подобное на ней.
String s = "";
String s2 = someUserInputVariale.toLowercase(); // where the user entered in ""
Что-то вроде этого может привести к тому, что s == s2
будет оцениваться как false.
Большое количество кода создает новые строки
без раскрытия вызова new String ()
.
Если вы используете поиск по коду Google, вы можете найти множество мест, где люди совершают ту же ошибку: google для файла: .java \ = \ = \ \ "\ " Конечно, это может быть правильная идиома в тщательно контролируемых обстоятельствах, но обычно это просто ошибка.
"" == 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), вычисляются при компиляции времени, а затем обрабатываются так, как если бы они были литералами.
- Строки, вычисляемые во время выполнения, создаются заново и, следовательно, отличаются.
- Результатом явного интернирования вычисленной строки является та же строка, что и любая ранее существующая буквальная строка с тем же содержание.
Если вы можете взять книгу Java Puzzlers Джошуа Блоха и Нила Гафтера и посмотреть на загадку 13 «Скотный двор» ... совет по этому поводу. Я собираюсь скопировать соответствующий текст:
«Вы, возможно, знаете, что константы времени компиляции типа String
интернированы [JLS 15.28]. Другими словами, любые два константные выражения типа String
, которые обозначают одну и ту же последовательность символов, представлены идентичными ссылками на объекты ... Ваш код редко, если вообще когда-либо, должен зависеть от интернирования строковых констант. Интернирование было разработано исключительно для уменьшения объема памяти виртуальной машины, а не как инструмент для программистов ... При сравнении ссылок на объекты,
Ожидаете ли вы, что «abcde» .substring (1,2)
и «zbcdefgh» .substring (1,2)
дадут то же самое Строковый объект?
Они обе дают "равные" подстроки, извлеченные из двух разных строк, но кажется вполне разумным, что это разные объекты, поэтому == видит их как разные.
Теперь рассмотрим, когда длина подстроки равна 0, подстрока (1, 1)
. Это дает строку нулевой длины, но неудивительно, что «abcde» .substring (1,1)
- это объект, отличный от «zbcdefgh» .substring (1,2)
и, следовательно, по крайней мере один из них отличается от "".
Насколько я понимаю, при компиляции кода Java в байт-код или при запуске программы одни и те же строки будут ссылаться на один и тот же объект в большинстве случаев для экономии памяти. Так что иногда вам сходит с рук == сравнения строк. Но это оптимизация компилятора, на которую нельзя положиться.
Но иногда случается, что компилятор решает не выполнять эту оптимизацию или программа не может увидеть, что строки совпадают, и внезапно проверка не выполняется, поскольку вы полагаетесь на некоторую базовую оптимизацию вуду. это зависит от реализации используемого вами jvm и так далее.
Поэтому использование equals всегда полезно. Для пустых строк есть другие возможности, такие как сравнение с length == 0 или, если вас не волнует обратная совместимость, есть string.empty ().
Также приходилось иметь дело с пробелами в именах путей. В конечном итоге я использовал рекурсию и для элемента в / path / *
:
Проверьте эту ссылку: http://mindprod.com/jgloss/string.html#COMPARISON в превосходном Canadian Mind Products Java & Internet Glossary ]. Стоит поставить закладку.
В 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
. Возвращает: строку с таким же содержимое как эта строка, но гарантированно из пула уникальных строки.
Почему бы не использовать:
if (value != null && value.length == 0) {
// do stuff (above could be "== null ||"
}
Вы должны использовать equals ()
, потому что ==
для объектов сравнивает ссылки, т.е. являются ли они одним и тем же объектом. Хотя во время компиляции Java находит идентичные строки и заставляет их использовать одну и ту же ссылку (строки неизменяемы), во время выполнения легко создать пустые строки с разными ссылками, где == не выполняется для вашего типичного намерения equals ()
.