Основной вопрос о Java: Строковое равенство

public class A {

    static String s1 = "I am A";

    public static void main(String[] args) {
        String s2 = "I am A";
        System.out.println(s1 == s2);
    }
}

Выше "верных" выводов программы. Оба - два различных идентификатора/объекта, как вывод "верен"?

Мое понимание - то, что JVM создаст другую ссылку для каждого объекта, раз так как вывод верен?

5
задан Joachim Sauer 24 July 2010 в 06:37
поделиться

5 ответов

Java управляет пулом литералов String . По возможности он использует эти литералы повторно. Следовательно, эти два объекта на самом деле являются одним и тем же объектом String , а == возвращает true.

Я считаю, что это называется интернированием строки

20
ответ дан 18 December 2019 в 05:24
поделиться

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

Если бы вы сделали

String s = new String("foo");
String t = new String("foo");

Тогда == вернет false, а s.equals (t) вернет true.

6
ответ дан 18 December 2019 в 05:24
поделиться

Потому что Спецификация языка Java говорит:

Строковые литералы или, в более общем смысле, строки, которые являются значениями постоянные выражения (§15.28) -are "интернированы", чтобы поделиться уникальными экземпляры, используя метод String.intern.

5
ответ дан 18 December 2019 в 05:24
поделиться

Это из-за оптимизации памяти, выполняемой компилятором ... а именно, констант String (т.е. - String s, созданных тем же ] String literal) используют тот же объект String , поскольку Strings неизменяемы. Оператор == просто проверяет, что два объекта являются одним и тем же реальным объектом.

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

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

Это из упомянутой выше ссылки ... страницы 30 - 31 моей книги.

5
ответ дан 18 December 2019 в 05:24
поделиться

Вы не сравниваете содержимое строк. Вы только сравниваете ссылки на объект. Вы должны использовать метод equal (который является членом класса String). Либо это, либо вы можете использовать метод compareTo (также в том же классе String), чтобы проверить, равно ли возвращаемое значение нулю.

Обратите внимание, что приведенный выше текст был более убедительным предложением к исходному состоянию вопроса, поскольку он оказалось, что ОП не знала о реальном процессе, происходящем за кулисами.

Другие парни, предлагавшие интернационал, были правы. Чтобы ответить на этот вопрос, у меня не хватило времени перейти к книге Java Puzzlers. Я подозревал что-то об установке той же ссылки во время компиляции, но я тоже не знал, как найти ссылку на это.

1
ответ дан 18 December 2019 в 05:24
поделиться
Другие вопросы по тегам:

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