Java: Почему равенство строк может быть доказано с помощью ==? - PullRequest
10 голосов
/ 07 декабря 2009

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

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

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

печатается правда.

Почему?

Ответы [ 3 ]

26 голосов
/ 07 декабря 2009

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

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

Если вы видите == тестирование "работы" сейчас, то это потому, что у вас действительно есть равные ссылки. Наиболее распространенная причина для этого, вероятно, связана с интернированием строковых литералов, но это было в 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.

3 голосов
/ 07 декабря 2009

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

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

1 голос
/ 05 октября 2014

Смотри, это хитрая концепция.

Существует разница между:

// 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");

Тогда два разных объекта были бы созданы в пуле строк в двух разных местах памяти и выполняли

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);

для объектов.

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