Если == сравнивает ссылки в Java, почему он оценивается как истинный с этими строками? - PullRequest
14 голосов
/ 27 октября 2010

Как указано, оператор == сравнивает ссылки на объекты, чтобы проверить, ссылаются ли они на один и тот же объект в куче.Если так, почему я получаю «Равный» для этого куска кода?

public class Salmon {
    public static void main(String[] args) {

        String str1 = "Str1";
        String str2 = "Str1";

        if (str1 == str2) {
            System.out.println("Equal");
        } else {
            System.out.println("Not equal");
        }
    }
}

Ответы [ 5 ]

38 голосов
/ 27 октября 2010

Программа напечатает Equal. (по крайней мере, с использованием горячей точки солнца и солнца Javac.) Здесь это показано на http://ideone.com/8UrRrk

Это связано с тем, что строковые литеральные константы хранятся в строковом пуле , а строковые ссылки могут использоваться повторно.

Дальнейшее чтение:


Это однако:

public class Salmon {
    public static void main(String[] args) {

        String str1 = "Str1";
        String str2 = new String("Str1");

        if (str1 == str2) {
            System.out.println("Equal");
        } else {
            System.out.println("Not equal");
        }
    }
}

Будет напечатано Not equal, поскольку new гарантированно предоставит новую ссылку.

Итак, практическое правило: Всегда сравнивайте строки, используя метод equals.

3 голосов
/ 27 октября 2010

Java сохраняет все строки в таблице строк во время выполнения. Ссылки на эти две строки идентичны, потому что в памяти они хранятся в одном и том же месте. Следовательно, Equal.

Ваше утверждение верно, что == сравнивает ссылки на объекты. Попробуйте то же самое с любым другим классом, кроме Strings, и вы не получите тот же результат.

3 голосов
/ 27 октября 2010

Этот код не будет печататься Equal.
Но если бы две строки были одинаковыми, этот случай был бы особенным.

Теперь, когда вы обновили свойкод, это тот случай:

Простое (но не совсем точное) объяснение состоит в том, что компилятор видит, что две строки одинаковы, и делает что-то вроде:

String str1 = "Str1";
String str2 = str1;

Здесь действительно происходит то, что компилятор увидит буквенную строку и поместит ее в «строковый пул букв».

Поскольку строка не может быть изменена (она неизменна), литеральные значения строк (те,найдены во время компиляции) помещаются в «пул».
Таким образом, если две разные литеральные строки, имеющие одинаковое содержимое (как в данном конкретном случае), память не тратится впустую для хранения «Str1» и «Str1"два раза.

2 голосов
/ 27 октября 2010

Люди, вы забыли, что процесс размещения буквенных строк в пуле называется "интернированием". Класс String имеет метод с именем intern (). Этот метод помещает любую строку в пул, даже если она изначально не находится в пуле (не буквально). Это означает, что код такой:

String a = "hello";
String b = new String("hello");
b = b.intern();

System.out.println(a == b);

напечатает "true". Теперь, зачем кому-то это нужно? Как вы можете себе представить, сравнение строк a.equals(b) может занять много времени, если строки имеют одинаковую длину, но разные в конце. (Просто посмотрите на исходный код .equals ().).

Однако непосредственное сравнение ссылок - это то же самое, что сравнение целых чисел (говорят указатели на C), что почти мгновенно.

Итак, что это дает вам? Скорость. Если вам придется сравнивать одни и те же строки много-много раз, производительность вашей программы значительно улучшится, если вы интернируете эти строки . Однако, если вы собираетесь сравнивать строки только один раз, прирост производительности не будет, поскольку сам процесс интернирования использует equals ().

Надеюсь, это объясняет это.

спасибо

0 голосов
/ 27 октября 2010

Комментарии выше суммировали это довольно хорошо.

У меня нет удобной среды Java, но попытка сделать следующее должна прояснить для вас ситуацию (надеюсь, это работает, как я и ожидал).

String str1 = "Str1";  
String str2 = "Str"; str2 += "1";

Должен теперь печатать Не равно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...