/ / “A” срещу “new String (“ a ”)” срещу “new String (“ a ”). Intern ()” в String Constant Pool (JDK 6) - java, string, jvm

"Нов" Струнгов ("a") "срещу" нов стринг ("a").

Знаех, че и двете от следните операции създават низа a в постоянния басейн по време на изпълнение:

String s = "a"
String s = new String("a")

Когато тествате тези на JVM, размерът на permgen е един и същ и за двата случая.


Следните фрагменти на код обаче се държат различно от това:

String s2 = null;
for (int i = 0; i < 100; i++)
{
s2 = s2 + i;
}

Използвайки .intern(), размерът на permgen се увеличава при всяка итерация:

String s2 = null;
for (int i = 0; i < 100; i++)
{
s2 = s2 + i;
s2.intern();
}

Защо това поведение се наблюдава? Прави s2.intern() добавете записи в пула? По какво се различава това от тези декларации?

String s = "a"
String s = new String("a")

Отговори:

4 за отговор № 1

Ето малко обяснение:

  • "a" създайте Низа "А" в стажантския басейн, ако вече не е налице
  • new String("a") защото параметърът е "А", низът "А" се създава в стажантския пул (ако вече не съществува) и копие на "А" е създаден от стажант
  • взе всички низове s s.intern() връща стажантско копие на този низ, ако присъства в стажовия пул. Ако не добавите този низ в интерналния пул и връща новото копие.

Справка за стажант() метод:

Когато стажантският метод се използва, ако пулътвече съдържа a низ, равен на този обект String, определен от равните (Object) метод, след това низът от пула се връща. В противен случай това String обект се добавя към пула и препратка към този String обектът е върнат.

Забележка: да се създаде String и не го добавяйте към стажантския басейн можеш използвайте масив от знаци като параметър на конструктора String:

char[] helloArray = { "h", "e", "l", "l", "o", "." };
String helloString = new String(helloArray);

Ето препратката към JLS където е обяснено, че в интерналния пул от низове присъства низ буквал:

Низовият буквал е препратка към екземпляр от клас String (§4.3.1, §4.3.3).

Нещо повече, низът буквално винаги се отнася до един и същ екземпляр от клас String. Това е така, защото струнни буквали - или, по-общо, струни които са стойностите на постоянните изрази (§15.28) - са "интернирани" така че да споделяте уникални екземпляри, използвайки метода String.intern.


Ето стъпка по стъпка обяснение към последния коментар:

// Creates the string "123", add it to the intern pool and assign "123" to s
String s = "123";

// s.intern() returns the intern string of s. Because s is already the
// string "123" present in the intern pool s and s.intern() are the same
System.out.println(s == s.intern());// true

// "123" is already in intern pool. new String("123") create a new String
// that equals "123" but it is a different object
String s2 = new String("123");

// It prints false because s2 is equals to "123", but not the same object
// because a new String was created in the preciding row
System.out.println(s2 == s);// false

// It prints true because s2.intern() returns the string present in the
// intern pool that is equals to s2. That string exists and is "123"
System.out.println(s2.intern() == s);  // true

Допълнителна бележка: За всеки низ s, който е равен на s2, s.intern () == s2.intern () също ако s == s2 връща невярно.

// If s equals s2 but are not the same
if (s.equals(s2) && s != s2) {
// THe intern string of s and s2 are always the same
System.out.println(s.intern() == s2.intern()); // prints always true
}

0 за отговор № 2

Тъй като интернираните струни са интернирани в JVM, те трябва да бъдат интернирани статично, което би изисквало механизмът да използва клас атрибут за кеширането, който би консумирал permgen памет.