Ответ 1
Поскольку экземпляры String
являются неизменяемыми, язык Java способен сделать некоторые оптимизации, в соответствии с которыми String
литералы (или, более общо, String
, значения которых константы времени компиляции) интернированы и фактически ссылаются на один и тот же объект (т.е. ==
).
JLS 3.10.5 Строковые литералы
Каждый строковый литерал является ссылкой на экземпляр
class String
. ОбъектыString
имеют постоянное значение. Строковые литералы или, в более общем смысле, строки, которые являются значениями константных выражений, "интернированы", чтобы обмениваться уникальными экземплярами, используя методString.intern
.
Вот почему вы получаете следующее:
System.out.println("yes" == "yes"); // true
System.out.println(99 + "bottles" == "99bottles"); // true
System.out.println("7" + "11" == "" + '7' + '1' + (char) (50-1)); // true
System.out.println("trueLove" == (true + "Love")); // true
System.out.println("MGD64" == "MGD" + Long.SIZE);
Сказано, что нужно сказать, что вы не должны полагаться на сравнение ==
для String
в целом и должны использовать equals
для не null
instanceof String
. В частности, не испытывайте соблазна intern()
всего вашего String
, чтобы вы могли использовать ==
, не зная, как работает интернирование строк.
Связанные вопросы
- Java String.equals против ==
- разница между строковым объектом и строковым литералом
- в чем преимущество строкового объекта по сравнению с строковым литералом
- Хорошо ли использовать java.lang.String.intern()?
Вкл new String(...)
Если по какой-то неподдельной причине вам нужно создать два объекта String
(которые по определению не являются ==
), но еще equals
, то вы можете, среди прочего, использовать этот конструктор:
public String(String original)
: Инициализирует вновь созданный объектString
, чтобы он представлял ту же последовательность символов, что и аргумент; Другими словами, вновь созданная строка является копией строки аргумента. Если явная копия оригинала не нужна, использование этого конструктора не нужно, так какStrings
являются неизменяемыми.
Таким образом, вы можете:
System.out.println("x" == new String("x")); // false
Оператор new
всегда создает новый объект, поэтому гарантированно печать false
. Тем не менее, это обычно не то, что вам действительно нужно делать. По возможности вы должны просто использовать строковые литералы вместо явного создания new String
для него.