Что делает сравнение ссылок (==) для некоторых строк в Java?
У меня есть следующие строки кодов для сравнения String. str1 не равно str2, что понятно, поскольку сравнивает ссылку на объект. Но тогда почему s1 равно s2?
String s1 = "abc";
String s2 = "abc";
String str1 = new String("abc");
String str2 = new String("abc");
if (s1==s2)
System.out.println("s1==s2");
else
System.out.println("s1!=s2");
if (str1==str2)
System.out.println("str1==str2");
else
System.out.println("str1!=str2");
if (s1==str1)
System.out.println("str1==s1");
else
System.out.println("str1!=s1");
Вывод:
s1==s2
str1!=str2
str1!=s1
Ответы
Ответ 1
Строковый пул констант по существу кэширует все строковые литералы, поэтому они являются одним и тем же объектом, поэтому вы видите вывод, который вы делаете для s1==s2
. Это, по сути, оптимизация в виртуальной машине, чтобы избежать создания нового строкового объекта каждый раз, когда объявляется литерал, который может очень быстро стать очень дорогостоящим! С вашим примером str1==str2
вы явно говорите виртуальной машине о создании новых строковых объектов, поэтому почему она неверна.
Как в стороне, вызов метода intern()
в любой строке добавит его в пул констант (и вернет String, который он добавил в пул). Это не обязательно хорошая идея для этого, однако, если вы не убедитесь, что вы имеете дело со строками, которые определенно будут использоваться в качестве констант, иначе вы можете создать сложную задачу для отслеживания утечек памяти.
Ответ 2
s1 и s2 - строковые литералы. Когда вы создаете новый строковый литерал, компилятор сначала проверяет, присутствует ли какой-либо литерал, представляющий его, в пуле строк или нет. Если есть один экземпляр, компилятор возвращает этот литерал, иначе компилятор создает новый.
Когда вы создали String s2
, компилятор возвращает String s1
из пула, как он уже был создан ранее. Вот почему s1
и s2
одинаковы. Это поведение называется интернированием.
Ответ 3
Это явление связано с Интерпретация строк.
В принципе, все строковые литералы "кэшируются" и повторно используются.
Ответ 4
Это происходит из-за интернирования строк. В этом вопросе документация Java говорит:
Все литералы и строковые константные выражения интернировано
И это объясняет, почему s1
и s2
одинаковы (эти две переменные указывают на одну и ту же интернированную строку)
Ответ 5
В Java одни и те же константные строки будут повторно использоваться. Чтобы s1
и s2
указывали на один и тот же объект "abc" и s1==s2
. Но когда вы используете new String("abc")
, будет создан другой объект. Так что s1 != str1
.
Ответ 6
Поскольку string
является неизменным в java, все string literals
кэшируются для повторного использования.
При создании объекта String с помощью new() оператор всегда создает новый объект в кучевой памяти. С другой стороны, если вы создаете объект, используя синтаксис строкового литерала, например. "Java", он может вернуть существующий объект из пула String (кеш объекта String в пространстве Perm gen, который теперь перемещается в кучу пространства в последнем выпуске Java), если он уже существует. В противном случае он создаст новый строковый объект и добавит пул строк для последующего повторного использования.
String s1 = new String("java");
String s2 = new String("java");
String s3 = "java";
String s4 = "java";
![введите описание изображения здесь]()
Обратитесь к этой ссылке