Почему неизменяемая новая строка («рыба»)! = Новая строка («рыба»)? - PullRequest
0 голосов
/ 21 октября 2011

Я помню, как читал раздел, возможно, в Эффективной Java Блоха, в котором говорилось, что в большинстве случаев, когда

String a = "fish";
String b = "fish";

, что a == b в большинстве случаев, потому что строки неизменяемы,Но из-за временного построения объектов или чего-то подобного новая строка («рыба») будет давать отдельную ссылку на объект.

Я просматривал главы Блоха об equals (), неизменности и создании объектов, но не могунайди этот бит я помню !!Вырывая мои волосы, кто-нибудь помнит, где описание того, почему это?Это может даже не быть в EJ , но я бы хотел найти его.Подсказка: где это объясняется - мой актуальный вопрос.

Ответы [ 3 ]

10 голосов
/ 21 октября 2011

Это не связано с неизменностью.Это способ, которым строки обрабатываются JVM.Строковый литерал с одинаковым содержимым представляет один и тот же объект («строковый литерал» означает примерно «текст, окруженный кавычками»).В JVM есть таблица строковых объектов, и у каждого строкового литерала есть ровно один объект в этой таблице.

Однако, когда вы точно создаете новый экземпляр, вы создаете новый строковый объект на основе строкового объекта, взятого из таблицы.

Из любой строки, образованной без использования литерала (но с помощью вызова toString (), создания экземпляров и т. Д.), Вы можете получить объект из таблицы jvm, вызвав str.intern().Метод intern() возвращает ровно один экземпляр для каждой существующей последовательности символов.new String("fish").intern() вернет тот же экземпляр, что и просто String s = "fish"

Следует запомнить две вещи:

  • никогда не использовать new String("something")
  • всегда сравнивать строки сequals(..) (если вы действительно не знаете, что делаете, и не документируете это)
0 голосов
/ 21 октября 2011

Если вы ищете точное описание, перейдите к определению: JLS § 3.10.5 Строковые литералы .

Пример кода, с которым вы должны быть знакомы:

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

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
0 голосов
/ 21 октября 2011

Я думаю, что вы ищете String.intern () метод, который поддерживает постоянный пул строк.

Оператор '==' сравнивает ссылки на объекты (адреса), тогда как .equals () - это вызов метода, который смотрит на семантическую эквивалентность.

Компилятор будет смотреть на String a = "fish" и String b = "fish", а затем может указывать или не указывать на один и тот же адрес. Однако, если вы делаете a.intern (); b.intern () тогда он, вероятно, поместит их в один и тот же пул строк и a == b.

...