String.intern это то же самое просто скопировать ссылку на объект в Java? - PullRequest
0 голосов
/ 18 декабря 2011

Делает:

String a = new String();
String b = a;

и делает:

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

то же самое?

На самом деле, ссылка все одинаковы, если я проверяю:

String a = new String("te");
String b = a.intern();
String c = a;
String d = "t" + "e";
System.out.print(a.equals(b));
System.out.print(b.equals(c));
System.out.print(a.equals(d));

Потому что когда-нибудь строка будет в пуле строк?

Ответы [ 4 ]

5 голосов
/ 18 декабря 2011

Ваши equals тесты не проверяют ссылки - они проверяют равенство строк .Вы должны использовать ==, чтобы проверить ссылки для identity .По сути, вы совершаете распространенную ошибку Java-новичка в обратном порядке - обычно люди используют ==, когда им следует использовать equals.В этом конкретном случае все они будут печатать false, потому что задействованы два объекта String (строка из пула констант и новая строка, созданная в первой строке).Если мы назовем эти # 1 и # 2 соответственно, мы получим:

a = #2 // Explicit call to string constructor
b = #1 // intern will return reference to constant pool instance
c = #2 // Direct assignment
d = #1 // Equivalent string constant, so reference to constant pool instance

Однако, вы можете найти это интересным:

String a = "te";
String b = a.intern();
String c = "t" + "e";
System.out.println(a == b); // true
System.out.println(a == c); // true

"te" и "t" + "e"равнозначные константные строковые выражения, поэтому в конечном итоге они становятся ссылками на одну строку, и вызов intern для строки, уже находящейся в пуле литералов, не даст никакого эффекта.

1 голос
/ 18 декабря 2011

Для начала: "t" + "e" - это строковый литерал, потому что он будет оптимизирован компилятором. Этот строковый литерал также используется в этой строке:

String a = new String("te");

Теперь конструктор String(String) создает физическую копию строки. Таким образом, это означает, что a и d являются не одним и тем же объектом.

Тогда: String.equals(String) сравнивает две строки. Он говорит, что содержимое 1016 * было равно, а не объект. Это означает, что у вас может быть два разных объекта String, которые имеют одинаковую последовательность символов, что приведет к возврату String.equals(String) true.

String.intern() помещает строку в пул строк, если ее еще нет. Но этот метод не может изменить сам объект. Таким образом, этот пример кода выведет false:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral.intern(); // "lit" was already in the String pool
                     // but `nonLiteral` is still `nonLiteral`
System.out.println(literal == nonLiteral); // false

Однако, если вы сделаете это: он вернет true:

String literal = "lit";
String nonLiteral = "abclit".substring(3); // equals "lit"
nonLiteral = nonLiteral.intern(); // "lit" was already in the String pool and
                                  // it will return the object `literal`.
                                  // Now the value is replaced.
System.out.println(literal == nonLiteral); // true
0 голосов
/ 18 декабря 2011

Если это строковое значение уже было интернировано из другого экземпляра String, intern() вернет более ранний экземпляр.

0 голосов
/ 18 декабря 2011

Использование equals не проверяет равенство ссылок.Он проверяет равенство содержимого строки.Вам нужно использовать == для проверки равенства ссылок.

Чтобы ответить на ваш вопрос, нет, это не то же самое.Первый фрагмент назначает две ссылки (a и b) на одну и ту же строку.Второй создает String, назначает его a, затем интернирует String и назначает String, которую пул интернирования возвращает b.Таким образом, a и b могут ссылаться на два разных экземпляра String (и, безусловно, будут, потому что пустая строка точно находится в пуле, поэтому intern () не будет возвращать STring, на которую ссылается a, но будет возвращать объединенную пустую строку)

...