String Literal/String new

0

///EDIT. Najpierw proszę popatrzeć na PS2, bo chyba to zrozumiałem, ale nie wiem czy dobrze myślę.

Cześć. Mam pytanie odnośnie String Poola i tworzeniu obiektów typu String.

Przed chwilą myślałem, że gdy robie String b = "a" to dodaje tylko do String Poola obiekt, jeżeli nie było takiego o takiej wartości. Gdy robie String a = new String("a") to dodaje na stertę obiekt i tyle.
Przed chwilą wyczytałem, że gdy wywołam linijkę z new: ** Two objects are created one for “a” in Heap and other in String pool area.**
Czyli, ma to wyglądać tak? screenshot-20190221153848.png

Co później będzie jak po String a = new String("a") zrobię String b = "a"?

Wg tej infografiki https://zapodaj.net/156e07c57744b.png.html](http://) żadnej strzałki nie ma do StringPoola po wykonaniu linijki z new

PS: Widzę, że nie podpisałem obrazka, kołko to StringPool, prostoką to Java Heap.
PS2:
Po kolejnych stronach chyba to to rozumiem. Gdy tworzymy Stringa za pomocą new to tworzymy dwa obiekty - w StringPoolu i na stercie (tak wiem, że SP jest częścią sterty, więc tak jakby 2 obiekty na stercie tworzymy), ale obiekt ma w sobie referencję do obiektu na stercie. Jak tworzymy Stringa za pomocą String Literal, to się tworzy obiekt tylko w StringPoolu. Jeżeli wcześniej już był identyczny String w StringPoolu czy to stworzony za pomocą new czy bez new, to ma on w sobie referencję do tego właśnie obiektu. Czy tak to działa?

0

Nie, jak Utworzysz nowy, taki sam string literal, to Masz dwa takie same obiekty(będą sobie równe, == zwróci true), a jak Utworzysz nowy taki sam, za pomocą new, to, będziesz miał nową referencję do tego samego obiektu (== zwróci false, natomiast isEqual() zwróci true).

0
lion137 napisał(a):

Nie, jak Utworzysz nowy, taki sam string literal, to Masz dwa takie same obiekty(będą sobie równe, == zwróci true), a jak Utworzysz nowy taki sam, za pomocą new, to, będziesz miał nową referencję do tego samego obiektu (== zwróci false, natomiast isEqual() zwróci true).

Tak ja to wiem. Wiem co zwróci kiedy false, a kiedy true, nie o to mi chodziło.

Napiszę jeszcze raz to co w PS2.
Gdy tworzę String za pomocą new to tworzą się dwa obiekty w String Poolu oraz w "Non-Poolu" czyli w heapie, ale poza StringPoolem.
Gdy stworzę później za pomocą String Literal obiekt o takie samej wartości co przedtem za pomocą new to już się nie utworzy obiekt w StrinPoolu, tylko referencja będzie wskazywać na ten obiekt, który został już utworzony za pomocą new. Jeżeli nie było takiej wartości, to tworzy się nowy obiekt.

Inna sytuacja:
Gdy stworzę najpierw za pomocą String Literal obiekt typu String, to wskakuje on do SP.
Gdy stworzę później obiekt typu string o tej samej wartości, to stworzy się tylko jeden obiekt w non-poolu.

Inna sytuacja:
Tworzę String literal, później kolejny, kolejny, to mam jeden obiekt w String poolu. Gdy później stworzę obiekt za pomocą new o takiej samej wartości czyli .equals()==true to stworzy się tylko jeden obiekt, czyli w sumie będą dwa.
Czy to co napisałem się zgadza? Jeżeli nie to w którym miejscu nie?

1

To w takim razie pytanie było źle zformułowane, albo ja się wyraziłem nie precyzyjnie. Jak Tworzysz literał, to Dostajesz nowy immutable string w SP, do którego referencją jest jego nazwa; tę referencję mozna zmienić,natomiast sam obiekt jest immutable, czyli, jak Przypiszesz do niego inną referencję, to dalej wskazuje ona na ten sam obiekt. W przypadku tworzenia za pomocą new, teoretycznie tworzymy dwa różne obiekty, ale może są optymalizowane, przez jakieś cashe czy coś, nie wiem. Acha, nie tworzymy dwóch obiektów, jeden obiekt reference type.

0
lion137 napisał(a):

W przypadku tworzenia za pomocą new, teoretycznie tworzymy dwa różne obiekty, ale może są optymalizowane, przez jakieś cashe czy coś, nie wiem. Acha, nie tworzymy dwóch obiektów, jeden obiekt reference type.

Tworzymy te dwa różne obiekty, ale referencje ma do tego z non-poola. Tak wyczytałem na internecie. Czyli zgadza się to co napisałeś. Zapomniałem o tym wspomnieć w poście. Aczkolwiek nie rozumiem czy coś co ja napisałem jest złego, czy nie.

0

Moim zdaniem String a = new String("a") jest dokładnie tym samym co:

String temp = "a"; // tutaj wyciągamy stringa z puli stringów
String a = new String(temp); // tutuaj tworzymy nowy obiekt na stercie

Gdzie temp jest unikalną nazwą.

0
Wibowit napisał(a):

Moim zdaniem String a = new String("a") jest dokładnie tym samym co:

String temp = "a";
String a = new String(temp);

Gdzie temp jest unikalną nazwą.

Zwraca ten sam hashcode.
Mnie bardziej chodzi o ten StringPool i tę stertę.
Czekam aż ktoś zweryfikuje ten post https://4programmers.net/Forum/1570318 Aczkolwiek zapomniałem dopisać jak @lion137 słusznie zauważył, że gdy użyjemy new to tworzą sie dwa obiekty, ale referencja jest do tego poza StringPoolem.

Jeszcze wczoraj bym powiedział, że new tworzy jeden obiekt tylko na stercie, a ja chce to wiedzieć na 100% a nie połowicznie.

2

Napiszę innymi słowami: w String a = new String("a"); będzie tyle samo alokacji na stercie i stringów w puli co w instrukcjach String temp = "a"; i String a = new String(temp); razem wziętych. To, że dodasz lub usuniesz sobie zmienną lokalną w żaden sposób nie wpłynie na to co pojawi się na stercie czy w puli (aczkolwiek dodatkowe zmienne referencyjne wpływają na działanie GC, ale to już inna bajka). Możesz sobie więc rozbić złożone instrukcje na mniejsze, używające zmiennych lokalnych i analizować te prostsze instrukcje.

Przykład ze złożonymi instrukcjami:

String a = new String(new String("a"));
String b = new String("b");
String a2 = "a";
String a3 = new String(a);

Po rozbiciu na mniejsze mamy:

// rozbijamy: String a = new String(new String("a"));
String temp1 = "a"; // pierwsze wystąpienie literału "a" - dodajemy do string puli
String temp2 = new String(temp1); // nowy obiekt na stercie poza pulą
String a = new String(temp2); // nowy obiekt na stercie poza pulą
// rozbijamy: String b = new String("b");
String temp3 = "b"; // pierwsze wystąpienie literału "b" - dodajemy do string puli
String b = new String(temp3); // nowy obiekt na stercie poza pulą
// rozbijamy: String a2 = "a";
String a2 = "a"; // kolejne wystąpienie literału "a" - jest już w string puli, więc nie dodajemy
// rozbijamy: String a3 = new String(a);
String a3 = new String(a); // nowy obiekt na stercie poza pulą
0
Wibowit napisał(a):

Napiszę innymi słowami: w String a = new String("a"); będzie tyle samo alokacji na stercie i stringów w puli co w instrukcjach String temp = "a"; i String a = new String(temp);

Tak, będzie tyle samo.
String a = new String("a"); tworzy dwa obiekty, referencje ma do non-poola.
Drugi przypadek.
Najpierw String temp = "a"; tworzy obiekt w StringPoolu, później String a = new String(temp); tworzy obiekt w non-poolu czyli w stercie poza StringPoolem.

Tak?

1

Tak. W obu przypadkach a wskazuje na obiekt poza pulą. W obu przypadkach tworzymy tyle samo obiektów, czy to tych poza pulą czy w puli.

0
Wibowit napisał(a):

Tak. W obu przypadkach a wskazuje na obiekt poza pulą. W obu przypadkach tworzymy tyle samo obiektów, czy to tych poza pulą czy w puli.

No i to już pisałem w tym poście wszystko https://4programmers.net/Forum/1570318 , ale nieważne :D
Dzięki za upewnienie się, że dobrze rozumiem.

0

Normalnie dwa stringi "aa" odnoszą się do tego samego obiektu. Jeśli stworzysz go inaczej, np new String("aa") albo "a" + "a" to wtedy będą się odnosić do innego, chyba że je zinternujesz albo same się zinternują

String one = "aa";
String two = "aa";                  // same  ==

String three = new String("aa");    // different  .equals()
String four = three.intern();       // same again  == 

String five = "a" + "a";            // different  .equals()
String six = five.intern();         // same again  ==

1 użytkowników online, w tym zalogowanych: 0, gości: 1