Подтвердить что ты не робот

Если == сравнивает ссылки в Java, почему она оценивает true с этими строками?

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

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");
        }
    }
}
4b9b3361

Ответ 1

Программа напечатает Equal. (по крайней мере, используя точку доступа Sun и солнце 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.

Ответ 2

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

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

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

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

Что на самом деле происходит здесь, так это то, что компилятор увидит литеральную строку и поместит ее в "Линейный пул строк".

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

Ответ 3

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

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

Ответ 4

Люди, вы забываете, что процесс размещения литеральных строк в пуле называется "интернированием". Класс 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().

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

спасибо

Ответ 5

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

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

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

Теперь нужно напечатать Неравномерно