Java: Почему доказательство равенства строк можно проверить с помощью ==?

Я узнал, что от дьявола проверять равенство строк с == вместо String.equals(), потому что каждая строка была ссылкой на свой собственный объект.

Но если я использую что-то вроде

System.out.println("Hello" == "Hello");

он выводит true.

Почему?

Ответ 1

Это не так. Это все еще плохо, но вы все равно будете тестировать ссылочное равенство вместо равенства ценности.

public class Test
{
    public static void main(String[] args)
    {
        String x = "hello";
        String y = new String(x);
        System.out.println(x == y); // Prints false
    }
}

Если вы видите == тестирование "работа" сейчас, то это потому, что вы действительно имеете равные ссылки. Наиболее распространенной причиной для этого было бы, вероятно, из-за интернирования литералов String, но это было в Java навсегда:

public class Test
{
    public static void main(String[] args)
    {
        String x = "hello";
        String y = "hel" + "lo"; // Concatenated at compile-time
        System.out.println(x == y); // Prints true
    }
}

Это гарантируется в разделе 3.10.5 спецификации языка Java:

Каждый строковый литерал является ссылкой (П. 4.3) к инстанции (п. 4.3.1, п. 12.5) класса String (п. 4.3.3). строка объекты имеют постоянное значение. строка литералы - или, в более общем смысле, строки которые являются значениями постоянной выражения (§15.28) - "интернированы", поэтому как обмениваться уникальными экземплярами, используя метод String.intern.

Ответ 2

Он не изменился. Однако Java Compiler использует string.intern(), чтобы убедиться, что идентичные строки в исходном коде компилируются для одного объекта String. Если, однако, вы загружаете String из файла или базы данных, это не будет тот же объект, если вы не принудительно это используете с помощью String.intern() или какого-либо другого метода.

Это плохая идея, и вы все равно должны использовать .equals()

Ответ 3

Посмотрите, это сложная концепция.

Существует различие между:

// These are String literals
String a = "Hiabc";
String b = "abc";
String c = "abc";

и

// These are String objects.
String a = new String("Hiabc");
String b = new String("abc");
String c = new String("abc"); 

Если ваши строки были объектами, т.е.

String b = new String("abc");
String c = new String("abc");

Затем два разных объекта были бы созданы в пуле String в двух разных ячейках памяти и выполняли

b == c  

привел бы false.

Но так как ваши String b и String c являются литералами,

b == c  

Результаты true. Это связано с тем, что не созданы два разных объекта. И оба a и b указывают на ту же строку в памяти стека.

В этом разница. Вы правы, == сравнивает место памяти. И в этом причина,

a.substring(2, 5) == b; // a,substring(2, 5) = "abc" which is at the location of b, and
b == c // will be true, coz both b and c are literals. And their values are compared and not memory locations.

Чтобы иметь две отдельные строки с одинаковыми значениями, но в разных местах в String pool и NOT stack memory, вам необходимо создать объекты String, как показано выше.

Итак,

a.substring(2, 5) == b; // and
b == c; // will be false. as not both are objects. Hence are stored on separate memory locations on the String pool.

вы должны использовать

a.substring(2, 5).equals(b);
b.equals(c);

в случае объектов.