JavaRush /Blog Java /Random-PL /Tłumaczenie: Tworzenie obiektów String w Javie - przy uży...
FellowSparrow
Poziom 12
Lvov

Tłumaczenie: Tworzenie obiektów String w Javie - przy użyciu „ ” lub konstruktora?

Opublikowano w grupie Random-PL
Oryginał: utworzyć ciąg Java za pomocą „” lub konstruktora? Autor: X Wang Tłumaczenie: Tworzenie obiektów ciągów w Javie - użycieW Javie ciąg można utworzyć na dwa sposoby:
String x = "abc";
String y = new String("abc");
Jaka jest różnica między używaniem podwójnych cudzysłowów a używaniem konstruktora?

1. Podwójne cytaty vs. Konstruktor

Odpowiedź na to pytanie można uzyskać, analizując dwa proste przykłady. Przykład 1:
String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True
a==btrue, ponieważ aoba bodnoszą się do tego samego obiektu - łańcucha zadeklarowanego jako literał (literał ciągu poniżej) w obszarze metody (odsyłamy czytelnika do źródła w naszym zasobie: 8 najlepszych diagramów do zrozumienia języka Java , diagram 8). Kiedy ten sam literał ciągu jest tworzony więcej niż raz, w pamięci przechowywana jest tylko jedna kopia ciągu, tylko jedna jego instancja (w naszym przypadku „abcd”). Nazywa się to „internowaniem ciągów”. Wszystkie stałe łańcuchowe przetwarzane w czasie kompilacji są automatycznie internowane w Javie. Przykład 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d);  // False
System.out.println(c.equals(d)); // True
c==dfalse, ponieważ codnoszą dsię do dwóch różnych obiektów w pamięci (na stercie). Różne obiekty zawsze mają różne odniesienia. Ten diagram ilustruje dwie opisane powyżej sytuacje: Tłumaczenie: Tworzenie obiektów ciągów w Javie - użycie

2. Internowanie ciągów na etapie realizacji programu

Autor dziękuje LukasEderowi (poniższy komentarz jest jego): Internowanie ciągów może nastąpić także podczas wykonywania programu, nawet jeśli za pomocą konstruktorów utworzone zostaną dwa ciągi:
String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d);  // Now true
System.out.println(c.equals(d)); // True

3. Kiedy używać cudzysłowów, a kiedy konstruktorów

Ze względu na to, że literał „abcd” jest zawsze typu String, użycie konstruktora spowoduje utworzenie dodatkowego, niepotrzebnego obiektu. Dlatego jeśli chcesz tylko utworzyć ciąg znaków, należy użyć podwójnych cudzysłowów. Jeśli rzeczywiście chcesz utworzyć nowy obiekt na stercie, powinieneś użyć konstruktora. Tutaj pokazane są przypadki użycia (oryginał) . (Poniżej zamieszczam przetłumaczony tekst. Jednak nadal gorąco polecam zapoznanie się z kodem komentatorów pod tym linkiem.)

Metoda substring() w JDK 6 i JDK 7

Metoda substring() w JDK 6 i JDK 7 Autor: X Wang Metoda substring(int beginIndex, int endIndex)w JDK 6 i JDK 7 jest inna. Znajomość tych różnic może pomóc w lepszym korzystaniu z tej metody. Dla ułatwienia czytania poniżej substring()będziemy mieli na myśli pełną składnię, tj. substring(int beginIndex, int endIndex).

1. Co robi substring()?

Metoda substring(int beginIndex, int endIndex)zwraca ciąg znaków rozpoczynający się od numeru beginIndexi kończący się na znaku numer endIndex-1.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
Wyjście:
bc

2. Co się stanie, gdy zostanie wywołana metoda substring()?

Być może wiesz, że ze względu na niezmienność x, przypisując x wynik x.substring(1,3), xwskazuje to na zupełnie nowy wiersz (patrz diagram): Tłumaczenie: Tworzenie obiektów ciągów w Javie - użycieJednak ten diagram nie jest całkowicie poprawny; nie pokazuje, co faktycznie dzieje się na stercie. To, co faktycznie dzieje się po wywołaniu, substring()różni się w JDK 6 i JDK 7.

3. substring() w JDK 6

Typ ciągu jest obsługiwany przez typ tablicy char. W JDK 6 klasa Stringzawiera 3 pola: char value[], int offset, int count. Służą do przechowywania aktualnej tablicy znaków, indeksu pierwszego znaku w tablicy, liczby znaków w linii. Po wywołaniu metoda substring()tworzy nowy wiersz, ale wartość zmiennej nadal wskazuje na tę samą tablicę na stercie. Różnica między dwoma ciągami znaków polega na liczbie znaków i wartości indeksu znaku początkowego w tablicy. Tłumaczenie: Tworzenie obiektów ciągów w Javie - użyciePoniższy kod jest uproszczony i zawiera jedynie podstawy ilustrujące problem.
//JDK 6
String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	return  new String(offset + beginIndex, endIndex - beginIndex, value);
}

4. Problem spowodowany substring() w JDK 6

Jeśli masz BARDZO długi ciąg, ale potrzebujesz tylko jego małej części, którą otrzymujesz za każdym razem, używając substring(). Spowoduje to problemy z wykonaniem, ponieważ potrzebujesz tylko małej części, ale nadal musisz przechowywać cały ciąg. W przypadku JDK 6 rozwiązaniem jest poniższy kod, który rzutuje ciąg na prawdziwy podciąg:
x = x.substring(x, y) + ""
Użytkownik STepeR sformułował pytanie (patrz jego komentarz) i wydawało się konieczne dodanie punktu 4. „Problem spowodowany substring()w JDK 6” jest bardziej rozbudowanym przykładem. Mam nadzieję, że to będzie odpowiedź i pomoże innym szybko dowiedzieć się, na czym polega problem. Oto kod:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
Zatem w JDK 7 bobiekty сtypu a Stringutworzone przez wywołanie metody substring()na obiekcie typu a Stringbędą odwoływać się do dwóch nowo utworzonych tablic na stercie - Lfor b, ongLfor c. Te dwie nowe tablice będą przechowywane na stercie WRAZ z oryginalną tablicą, do aLongLongStringktórej odwołuje się a. Te. oryginalna tablica nigdzie nie znika. Wróćmy teraz do JDK 6. W JDK 6 sterta zawiera pojedynczą tablicę aLongLongString. Po wykonaniu linii kodu
String b = a.substring(1, 2);
String c = a.substring(2, 6);
obiekty bodnoszą się cdo tej samej tablicy w stercie, odpowiadającej obiektowi a: b- do elementów od 1. do 2. indeksu, c- do elementów od 2. do 6. indeksu (numeracja zaczyna się od 0, dla przypomnienia). Te. Oczywiście każdy dalszy dostęp do zmiennych blub c w JDK 6 faktycznie spowoduje, że żądane elementy oryginalnej tablicy zostaną „wliczone” do sterty. W JDK 7 dalszy dostęp do zmiennych blub c spowoduje dostęp do niezbędnych mniejszych tablic, które zostały już utworzone i „żyją” na stercie. Te. Najwyraźniej JDK 7 zużywa fizycznie więcej pamięci w takich sytuacjach. Ale wyobraźmy sobie możliwą opcję: pewne podciągi zmiennej są przypisane do zmiennych bi w przyszłości wszyscy będą używać tylko ich - obiektów i . Nikt już po prostu nie ma dostępu do zmiennej a, nie ma do niej żadnych odniesień (to właśnie ma na myśli autor artykułu). W rezultacie w pewnym momencie zostaje uruchomiony moduł zbierający śmieci i (oczywiście w najbardziej ogólnej formie) otrzymujemy 2 różne sytuacje: JDK 6 : obiekt zostaje zniszczony (zebrany śmieci) , ALE - oryginalna ogromna tablica na stosie żyje; jest stale używany i . JDK 7: obiekt a zostaje zniszczony wraz z oryginalną tablicą na stercie. To jest punkt w JDK 6, który może prowadzić do wycieku pamięci. cabcabc

5. substring() w JDK 7

Metoda została ulepszona w JDK 7. W JDK 7 substring()faktycznie tworzy nową tablicę na stercie. Tłumaczenie: Tworzenie obiektów ciągów w Javie - użycie
//JDK 7
public String(char value[], int offset, int count) {
	//check boundary
	this.value = Arrays.copyOfRange(value, offset, offset + count);
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	int subLen = endIndex - beginIndex;
	return new String(value, beginIndex, subLen);
}
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION