String Literal/String new

String Literal/String new
J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
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?

edytowany 6x, ostatnio: jajko1233
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:30 minut
  • Postów:4935
0

J1
Mi nie chodzi o porównywanie Stringów, a o zamysł tworzenia. Już na tej stronie byłem i na wielu wielu innych i to co napisałem w PS2 udało mi się wyłuskać. Dobrze tam napisałem?
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:30 minut
  • Postów:4935
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).


J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
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?

edytowany 1x, ostatnio: jajko1233
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:30 minut
  • Postów:4935
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.


edytowany 1x, ostatnio: lion137
J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
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.

lion137
Przestudiuj dokładnie cały ten wątek na so, to Ci się rozjaśni całkowicie.
J1
@lion137: naprawdę przeczytałem i wiele innych i chce sie tylko upewnić czy dobrze to rozumiem i cały czas liczę na odpowiedź o fragment który ewentualnie źle zrozumiałem bądź czy dobrze zrozumiałem.
lion137
Nie wiem, jeśli Uznajesz mój ostatni post, i ten wątek, to Rozumiesz (jakbyś nie uznał i pokazał, to też Rozumiesz, pewnie nawet lepiej)
J1
@lion137: tak, ale ja wypisałem kilka przypadków tworzenia po sobie Stringów za pomocą new i string literal, a Ty tylko co się stanie po zrobieniu tego i tego. :P Nie wiesz czy nie czytałeś, czy nie wiesz, że nie wiesz? :D
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około godziny
0

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

Kopiuj
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ą.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
0
Wibowit napisał(a):

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

Kopiuj
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.

edytowany 1x, ostatnio: jajko1233
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około godziny
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:

Kopiuj
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:

Kopiuj
// 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ą

"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
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?

edytowany 2x, ostatnio: jajko1233
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około godziny
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.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
J1
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Postów:104
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.

Riddle
Administrator
  • Rejestracja:prawie 15 lat
  • Ostatnio:2 minuty
  • Lokalizacja:Laska, z Polski
  • Postów:10085
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ą

Kopiuj
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  ==
edytowany 2x, ostatnio: Riddle
Zobacz pozostały 1 komentarz
Riddle
I taka automatyczna deduplikacja to nie jest "same się zinternują"?
Wibowit
Nie. Deduplikacja dotyczy tablic, a nie obiektów typu String. Jeśli stworzysz dwa identyczne Stringi za pomocą new to operator == zawsze zwróci false niezależnie od tego czy tablica znaków pod spodem tych Stringów jest zdeduplikowana czy nie. == na referencjach typu String nie zagląda do środka tych Stringów. To powinno być oczywiste :) Ogólnie operator == na dwóch referencjach typu A nie zagląda czy w środku obiektów do których prowadzą te referencje są jakieś pola typu B które są tożsame. Byłoby to absurdalne.
Wibowit
Deduplikacja jest niewidoczna dla programisty, no może oprócz tego, że zużycie pamięci maleje. Po to się deduplikuje tablice znaków, a nie same Stringi by właśnie było to niewidoczne, by nie zmieniało w ogóle semantyki programu. Niezależnie od tego czy masz włączoną deduplikację tablic znaków pod Stringami operator == na Stringach daje ten sam wynik.
Wibowit
Internowanie Stringów (tych spoza puli stałych Stringów) natomiast robi się wprost, bo to zmienia semantykę programu, wpływa na porównania Stringów przez ==.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.