Ciągi Java: „Ciąg s = nowy ciąg („ głupi ”);”


85

Jestem facetem C ++ uczącym się języka Java. Czytam Effective Java i coś mnie zdezorientowało. Mówi, żeby nigdy nie pisać takiego kodu:

String s = new String("silly");

Ponieważ tworzy niepotrzebne Stringprzedmioty. Ale zamiast tego powinno być napisane w ten sposób:

String s = "No longer silly";

Na razie ok ... Jednak biorąc pod uwagę tę klasę:

public final class CaseInsensitiveString {
    private String s;
    public CaseInsensitiveString(String s) {
        if (s == null) {
            throw new NullPointerException();
        }
        this.s = s;
    }
    :
    :
}

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
  1. Dlaczego pierwsze stwierdzenie jest w porządku? Nie powinno

    CaseInsensitiveString cis = "Polish";

  2. Jak mam się CaseInsensitiveStringzachowywać, Stringaby powyższe stwierdzenie było w porządku (z rozszerzeniem i bez niego String)? Co takiego jest w String'u, że można po prostu przekazać go w taki sposób? Z mojego punktu widzenia w Javie nie ma koncepcji „konstruktora kopiującego”?


2
String str1 = "foo"; String str2 = "foo"; Zarówno str1, jak i str2 należą do tego samego obiektu String, "foo", b'coz dla Javy zarządza ciągami w StringPool, więc jeśli nowa zmienna odnosi się do tego samego ciągu, nie tworzy kolejnego, a raczej przypisuje tę samą alerady obecną w StringPool. Ale kiedy to zrobimy: String str1 = new String ("foo"); String str2 = new String ("foo"); Tutaj zarówno str1, jak i str2 należą do różnych obiektów, b'coz new String () na siłę tworzy nowy obiekt String.
Akash5288

Odpowiedzi:


110

Stringto specjalna wbudowana klasa języka. Jest przeznaczony tylko do Stringzajęć, w których nie powinieneś mówić

String s = new String("Polish");

Ponieważ literał "Polish"jest już typu Stringi tworzysz dodatkowy, niepotrzebny obiekt. Mówiąc o każdej innej klasie

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

jest właściwą (i jedyną w tym przypadku) czynnością do zrobienia.


8
Drugim ważnym punktem jest to, że puszka kompilator fantazyjne internig / rozmnożeniowego-stuff z napisowych, które niekoniecznie są możliwe z takim dziwnym FunctionCall jak „String (dosłowne)”
Tetha

4
Ponieważ nigdy nie powinieneś dzwonić new String("foo"), możesz zadać sobie pytanie, dlaczego konstruktor new String(String)istnieje. Odpowiedź brzmi, że czasami jest to dobre zastosowanie: stackoverflow.com/a/390854/1442870
Enwired

FYI, powyższy komentarz Tety zawiera błędną pisownię słowa „interning”, jak w przypadku strun interning .
Basil Bourque

56

Uważam, że główną zaletą używania formy dosłownej (tj. „Foo” zamiast new String („foo”)) jest to, że wszystkie literały String są „internowane” przez maszynę wirtualną. Innymi słowy, jest dodawany do puli w taki sposób, że jakikolwiek inny kod, który tworzy ten sam ciąg, użyje z puli String zamiast tworzenia nowej instancji.

Aby to zilustrować, poniższy kod wypisze prawdę w pierwszym wierszu, ale fałsz w drugim:

System.out.println("foo" == "foo");
System.out.println(new String("bar") == new String("bar"));

14
Podobnie, dlatego FindBugs mówi ci, aby zastąpić „nowy Integer (N)” „Integer.valueOf (N)” - z powodu tego internowania.
Paul Tomblin

6
Powinieneś także dodać „foo” == new String („foo”). Intern ()
James Schek

4
Poprawka: literały ciągów znaków mają wskazywać to samo odwołanie przez kompilator, a nie maszynę wirtualną. Maszyna wirtualna może internować obiekty typu String w czasie wykonywania, więc druga linia może zwracać prawdę lub fałsz!
Craig P. Motlin

1
@Motlin: Nie jestem pewien, czy to prawda. Javadoc dla klasy String nakazuje, że „wszystkie ciągi literałów i wyrażenia stałe o wartości łańcuchowej są internowane”. Możemy więc polegać na internowaniu literałów, co oznacza, że ​​"foo" == "foo" zawsze powinno zwracać true.
Leigh,

3
@Leigh Tak, literały są internowane, ale przez kompilator, a nie maszynę wirtualną. Motlin dąży do tego, że maszyna wirtualna może dodatkowo umieszczać ciągi znaków, a zatem to, czy new String ("bar") == new String ("bar") -> false jest zależne od implementacji, czy nie.
Aaron Maenpaa

30

Łańcuchy są traktowane trochę specjalnie w java, są niezmienne, więc można je bezpiecznie obsługiwać przez zliczanie referencji.

Jeśli piszesz

String s = "Polish";
String t = "Polish";

wtedy s i t faktycznie odnoszą się do tego samego obiektu, a s == t zwróci prawdę, ponieważ "==" dla obiektów odczytanych "jest tym samym obiektem" (lub nie mogę, w każdym razie, nie jestem pewien, czy jest to część rzeczywista specyfikacja języka lub po prostu szczegół implementacji kompilatora - więc może nie można na tym polegać).

Jeśli piszesz

String s = new String("Polish");
String t = new String("Polish");

wtedy s! = t (ponieważ jawnie utworzyłeś nowy łańcuch), chociaż s.equals (t) zwróci prawdę (ponieważ string dodaje to zachowanie do równości).

To, co chcesz napisać,

CaseInsensitiveString cis = "Polish";

nie może działać, ponieważ myślisz, że cudzysłowy są rodzajem konstruktora zwarciowego dla twojego obiektu, podczas gdy w rzeczywistości działa to tylko dla zwykłego starego java.lang.Strings.


+1 za wzmiankę o niezmienności, która jest dla mnie prawdziwym powodem, dla którego w java pisze się strA = strBzamiast strA = new String(strB). to naprawdę nie ma wiele wspólnego z internowaniem stringów.
kritzikratzi

Nie są obsługiwane przez liczenie referencji. Pule ciągów są wymagane przez JLS.
Markiz Lorne,

20
String s1="foo";

dosłownie trafi do puli, a s1 będzie się odnosić.

String s2="foo";

tym razem sprawdzi, czy literał "foo" jest już dostępny w StringPool, czy nie, ponieważ teraz istnieje, więc s2 będzie odnosił się do tego samego literału.

String s3=new String("foo");

Literał "foo" zostanie najpierw utworzony w StringPool, a następnie za pomocą konstruktora string arg Zostanie utworzony obiekt String, tj. "foo" w stercie w wyniku utworzenia obiektu przez operatora new, a następnie s3 odniesie się do niego.

String s4=new String("foo");

tak samo jak s3

więc System.out.println(s1==s2);// **true** due to literal comparison.

i System.out.println(s3==s4);// **false** due to object

porównanie (s3 i s4 są tworzone w różnych miejscach na stercie)


1
Nie używaj formatowania cytatów w przypadku tekstu, który nie jest cytowany, i używaj formatowania kodu dla kodu.
Markiz Lorne,

12

Strings są wyjątkowe w Javie - są niezmienne, a stałe łańcuchowe są automatycznie zamieniane w Stringobiekty.

Nie ma możliwości, aby Twój SomeStringClass cis = "value"przykład odnosił się do innych zajęć.

Nie możesz też rozszerzać String, ponieważ jest zadeklarowany jako final, co oznacza, że ​​żadne podklasy nie są dozwolone.


7

Ciągi Java są interesujące. Wygląda na to, że odpowiedzi dotyczyły niektórych interesujących punktów. Oto moje dwa centy.

ciągi znaków są niezmienne (nigdy nie możesz ich zmienić)

String x = "x";
x = "Y"; 
  • Pierwsza linia utworzy zmienną x, która będzie zawierać wartość ciągu „x”. JVM zajrzy do swojej puli wartości łańcuchowych i sprawdzi, czy istnieje „x”, a jeśli tak, wskaże na nią zmienną x, a jeśli nie istnieje, utworzy ją i dokona przypisania
  • Druga linia usunie odniesienie do „x” i sprawdzi, czy „Y” istnieje w puli wartości łańcuchowych. Jeśli istnieje, przypisze go, jeśli nie, utworzy go najpierw, a następnie przypisanie. Gdy wartości łańcuchowe są używane lub nie, przestrzeń pamięci w puli wartości łańcuchowych zostanie odzyskana.

porównania ciągów są zależne od tego, co porównujesz

String a1 = new String("A");

String a2 = new String("A");
  • a1 nie równa się a2
  • a1i a2są odniesieniami do obiektów
  • Gdy string jest jawnie zadeklarowany, tworzone są nowe instancje, a ich odwołania nie będą takie same.

Myślę, że jesteś na złej drodze, próbując użyć klasy niewrażliwości na wielkość liter. Zostaw struny w spokoju. To, na czym naprawdę Ci zależy, to sposób wyświetlania lub porównywania wartości. Użyj innej klasy, aby sformatować ciąg lub dokonać porównań.

to znaczy

TextUtility.compare(string 1, string 2) 
TextUtility.compareIgnoreCase(string 1, string 2)
TextUtility.camelHump(string 1)

Ponieważ tworzysz klasę, możesz sprawić, że porównania zrobią, co chcesz - porównaj wartości tekstowe.


Kompilator tworzy pulę ciągów, a nie JVM. Zmienne nie zawierają obiektów, one się do nich odnoszą. Przestrzeń puli ciągów dla literałów ciągów nigdy nie jest odzyskiwana.
Markiz Lorne,

6

Nie możesz. Elementy w podwójnych cudzysłowach w Javie są specjalnie rozpoznawane przez kompilator jako ciągi znaków i niestety nie można tego przesłonić (ani rozszerzyć java.lang.String- jest to zadeklarowane final).


finał to tu czerwony śledź. Nawet jeśli String nie był ostateczny, przedłużenie String nie pomogłoby mu w tym przypadku.
Darron

1
Myślę, że masz na myśli, że na szczęście nie możesz tego zmienić. :)
Craig P. Motlin

@Motlin: Ha! możesz mieć rację. Myślę, że czytałem gdzieś, że Java została zaprojektowana, aby powstrzymać każdego, kto kiedykolwiek zrobiłby coś głupiego, celowo wykluczając coś tak interesującego ...
Dan Vinton,

6

Najlepszym sposobem odpowiedzi na Twoje pytanie jest zapoznanie się z „Stałą pulą łańcuchową”. W java obiekty typu string są niezmienne (tj. Ich wartości nie mogą być zmienione po ich zainicjowaniu), więc podczas edycji obiektu string tworzysz nowy edytowany obiekt string, w którym stary obiekt po prostu pływa w specjalnej pamięci zwanej „stringiem” stała pula ”. tworzenie nowego obiektu ciągu przez

String s = "Hello";

utworzy tylko obiekt typu string w puli, a referencje będą się do niego odnosić, ale przy użyciu

String s = new String("Hello");

tworzysz dwa obiekty łańcuchowe: jeden w puli, a drugi w stercie. odniesienie będzie odnosić się do obiektu w stercie.


4

- Jak sprawić, by CaseInsensitiveString zachowywał się jak String, aby powyższa instrukcja była w porządku (zi bez rozszerzenia String)? Co takiego jest w String, że można po prostu przekazać go tak dosłownie? Z mojego punktu widzenia w Javie nie ma koncepcji „konstruktora kopiującego”, prawda?

Dość już powiedziano od pierwszego punktu. „Polski” jest ciągiem znaków i nie można go przypisać do klasy CaseInsentiviveString.

Teraz o drugim punkcie

Chociaż nie możesz tworzyć nowych literałów, możesz postępować zgodnie z pierwszym punktem tej książki, aby zastosować „podobne” podejście, więc poniższe stwierdzenia są prawdziwe:

    // Lets test the insensitiveness
    CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
    CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

    assert cis5 == cis6;
    assert cis5.equals(cis6);

Oto kod.

C:\oreyes\samples\java\insensitive>type CaseInsensitiveString.java
import java.util.Map;
import java.util.HashMap;

public final class CaseInsensitiveString  {


    private static final Map<String,CaseInsensitiveString> innerPool 
                                = new HashMap<String,CaseInsensitiveString>();

    private final String s;


    // Effective Java Item 1: Consider providing static factory methods instead of constructors
    public static CaseInsensitiveString valueOf( String s ) {

        if ( s == null ) {
            return null;
        }
        String value = s.toLowerCase();

        if ( !CaseInsensitiveString.innerPool.containsKey( value ) ) {
             CaseInsensitiveString.innerPool.put( value , new CaseInsensitiveString( value ) );
         }

         return CaseInsensitiveString.innerPool.get( value );   
    }

    // Class constructor: This creates a new instance each time it is invoked.
    public CaseInsensitiveString(String s){
        if (s == null) {
            throw new NullPointerException();
         }         
         this.s = s.toLowerCase();
    }

    public boolean equals( Object other ) {
         if ( other instanceof CaseInsensitiveString ) {
              CaseInsensitiveString otherInstance = ( CaseInsensitiveString ) other;
             return this.s.equals( otherInstance.s );
         }

         return false;
    }


    public int hashCode(){
         return this.s.hashCode();
    }

// Przetestuj klasę za pomocą słowa kluczowego „assert”

    public static void main( String [] args ) {

        // Creating two different objects as in new String("Polish") == new String("Polish") is false
        CaseInsensitiveString cis1 = new CaseInsensitiveString("Polish");
        CaseInsensitiveString cis2 = new CaseInsensitiveString("Polish");

        // references cis1 and cis2 points to differents objects.
        // so the following is true
        assert cis1 !=  cis2;      // Yes they're different
        assert cis1.equals(cis2);  // Yes they're equals thanks to the equals method

        // Now let's try the valueOf idiom
        CaseInsensitiveString cis3 = CaseInsensitiveString.valueOf("Polish");
        CaseInsensitiveString cis4 = CaseInsensitiveString.valueOf("Polish");

        // References cis3 and cis4 points to same  object.
        // so the following is true
        assert cis3 == cis4;      // Yes they point to the same object
        assert cis3.equals(cis4); // and still equals.

        // Lets test the insensitiveness
        CaseInsensitiveString cis5 = CaseInsensitiveString.valueOf("sOmEtHiNg");
        CaseInsensitiveString cis6 = CaseInsensitiveString.valueOf("SoMeThInG");

        assert cis5 == cis6;
        assert cis5.equals(cis6);

        // Futhermore
        CaseInsensitiveString cis7 = CaseInsensitiveString.valueOf("SomethinG");
        CaseInsensitiveString cis8 = CaseInsensitiveString.valueOf("someThing");

        assert cis8 == cis5 && cis7 == cis6;
        assert cis7.equals(cis5) && cis6.equals(cis8);
    }

}

C:\oreyes\samples\java\insensitive>javac CaseInsensitiveString.java


C:\oreyes\samples\java\insensitive>java -ea CaseInsensitiveString

C:\oreyes\samples\java\insensitive>

Oznacza to, że należy utworzyć wewnętrzną pulę obiektów CaseInsensitiveString i stamtąd zwrócić odpowiednią instancję.

W ten sposób operator „==” zwraca prawdę dla dwóch odniesień do obiektów reprezentujących tę samą wartość .

Jest to przydatne, gdy podobne obiekty są używane bardzo często, a tworzenie kosztów jest kosztowne.

Dokumentacja klasy string stwierdza, że ​​klasa używa puli wewnętrznej

Klasa nie jest kompletna, pojawiają się interesujące problemy, gdy próbujemy przejść przez zawartość obiektu podczas implementacji interfejsu CharSequence, ale ten kod jest wystarczająco dobry, aby pokazać, jak można zastosować ten element w Księdze.

Należy zauważyć, że przy użyciu obiektu internalPool odwołania nie są zwalniane, a tym samym nie mogą być usuwane z pamięci, co może stać się problemem, jeśli zostanie utworzonych wiele obiektów.

Działa dla klasy String, ponieważ jest intensywnie użytkowana, a pula składa się wyłącznie z obiektu „internowanego”.

Działa dobrze również dla klasy Boolean, ponieważ są tylko dwie możliwe wartości.

I wreszcie jest to również powód, dla którego wartość valueOf (int) w klasie Integer jest ograniczona do -128 do 127 wartości int.


3

W pierwszym przykładzie tworzysz „głupiutki” String, a następnie przekazujesz go jako parametr do konstruktora kopiującego innego Stringa, co tworzy drugi ciąg, identyczny z pierwszym. Ponieważ ciągi Java są niezmienne (coś, co często kłuje ludzi przyzwyczajonych do ciągów C), jest to niepotrzebne marnowanie zasobów. Zamiast tego powinieneś użyć drugiego przykładu, ponieważ pomija on kilka niepotrzebnych kroków.

Jednak literał String nie jest CaseInsensitiveString, więc nie możesz zrobić tego, co chcesz w ostatnim przykładzie. Ponadto nie ma sposobu na przeciążenie operatora rzutowania, tak jak w C ++, więc dosłownie nie ma sposobu, aby zrobić to, co chcesz. Zamiast tego musisz przekazać go jako parametr do konstruktora swojej klasy. Oczywiście prawdopodobnie użyłbym String.toLowerCase () i skończyłbym z tym.

Ponadto CaseInsensitiveString powinna implementować interfejs CharSequence, a także prawdopodobnie interfejsy Serializable i Comparable. Oczywiście, jeśli zaimplementujesz Comparable, powinieneś również zastąpić equals () i hashCode ().


3

Tylko dlatego, że masz słowo Stringw swojej klasie, nie oznacza, że ​​masz wszystkie specjalne funkcje wbudowanej Stringklasy.


3

CaseInsensitiveStringnie jest, Stringchociaż zawiera String. StringDosłowny np „przykład” może być przypisana tylko do String.


2

CaseInsensitiveString i String to różne obiekty. Nie możesz zrobić:

CaseInsensitiveString cis = "Polish";

ponieważ „Polish” to String, a nie CaseInsensitiveString. Jeśli String rozszerzone CaseInsensitiveString String, wszystko będzie w porządku, ale oczywiście tak nie jest.

I nie martw się o konstrukcję tutaj, nie będziesz robił zbędnych przedmiotów. Jeśli spojrzysz na kod konstruktora, jedyne, co robi, to przechowywanie odniesienia do przekazanego ciągu. Nie tworzy się nic dodatkowego.

W przypadku String s = new String ("foobar") robi coś innego. Najpierw tworzysz literał „foobar”, a następnie tworzysz jego kopię, konstruując z niego nowy ciąg. Nie ma potrzeby tworzenia tej kopii.


Nawet jeśli przedłużysz String to nie zadziała. Potrzebowałbyś String, aby rozszerzyć CaseInsensitiveString.
Darron

w każdym razie jest to niemożliwe, albo dlatego, że ciąg jest wbudowany, albo dlatego, że został ogłoszony jako ostateczny
Łukasz

2

kiedy mówią, żeby pisać

String s = "Silly";

zamiast

String s = new String("Silly");

mają na myśli to podczas tworzenia obiektu String, ponieważ obie powyższe instrukcje tworzą obiekt String, ale nowa wersja String () tworzy dwa obiekty String: jeden w stercie, a drugi w puli stałych łańcuchów. Stąd więcej pamięci.

Ale kiedy piszesz

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");

nie tworzysz String zamiast tego tworzysz obiekt klasy CaseInsensitiveString. Dlatego musisz użyć nowego operatora.


1

Jeśli dobrze to zrozumiałem, twoje pytanie oznacza, dlaczego nie możemy stworzyć obiektu poprzez bezpośrednie przypisanie mu wartości, nie ograniczajmy go do klasy Wrapper of String w java.

Odpowiadając, powiedziałbym tylko, że czysto obiektowe języki programowania mają pewne konstrukcje i mówi, że wszystkie literały zapisane samodzielnie mogą być bezpośrednio przekształcone w obiekt danego typu.

To dokładnie oznacza, że ​​jeśli interpreter widzi 3, zostanie przekonwertowany na obiekt Integer, ponieważ integer jest typem zdefiniowanym dla takich literałów.

Jeśli interpreter widzi cokolwiek w cudzysłowie, np. „A”, to bezpośrednio utworzy obiekt typu znak, nie musisz go określać, ponieważ język definiuje dla niego domyślny obiekt znaku.

Podobnie, jeśli interpreter zobaczy coś w "", zostanie to potraktowane jako obiekt swojego domyślnego typu, tj. Łańcuch. To jest kod natywny działający w tle.

Dzięki wykładowi wideo MIT 6.00, gdzie dostałem podpowiedź do tej odpowiedzi.


0

W Javie składnia „text” tworzy instancję klasy java.lang.String. Przydzial:

String foo = "text";

jest prostym przypisaniem, bez konstruktora kopiującego.

MyString bar = "text";

Cokolwiek robisz, jest nielegalne, ponieważ klasa MyString nie jest ani java.lang.String, ani nadklasą java.lang.String.


0

Po pierwsze, nie możesz stworzyć klasy, która pochodzi od klasy String, ponieważ String jest klasą końcową. A java zarządza ciągami inaczej niż inne klasy, więc możesz to zrobić tylko za pomocą String

String s = "Polish";

Ale mimo swojej klasy musisz wywołać konstruktora. Więc ten kod jest w porządku.


0

Dodam tylko, że Java ma konstruktory kopiujące ...

Cóż, to zwykły konstruktor z obiektem tego samego typu co argument.


2
To wzorzec projektowy, a nie konstrukcja językowa. W Javie jest bardzo niewiele zastosowań, w których konstruktor kopiujący byłby interesujący, ponieważ wszystko jest zawsze „przez odniesienie”, a każdy obiekt ma tylko jedną kopię. W rzeczywistości robienie kopii spowodowałoby naprawdę DUŻO problemów.
Bill K

0

W większości wersji JDK obie wersje będą takie same:

String s = new String ("głupie");

String s = "Już nie głupi";

Ponieważ ciągi są niezmienne, kompilator przechowuje listę stałych łańcuchowych i jeśli spróbujesz utworzyć nowy, najpierw sprawdzi, czy ciąg jest już zdefiniowany. Jeśli tak, zwracane jest odwołanie do istniejącego niezmiennego ciągu.

Aby wyjaśnić - kiedy mówisz „String s =”, definiujesz nową zmienną, która zajmuje miejsce na stosie - wtedy czy powiesz „Już nie głupi” czy nowy Ciąg („głupi”) dokładnie to samo się dzieje - nowa ciąg stały jest wkompilowany w twoją aplikację i wskazuje na to odniesienie.

Nie widzę tutaj różnicy. Jednak dla twojej własnej klasy, która nie jest niezmienna, to zachowanie jest nieistotne i musisz zadzwonić do swojego konstruktora.

UPDATE: Myliłem się! Opierając się na głosowaniu negatywnym i załączonym komentarzu, przetestowałem to i zdałem sobie sprawę, że moje rozumienie jest błędne - new String („Silly”) rzeczywiście tworzy nowy ciąg zamiast ponownie wykorzystywać istniejący. Nie jestem pewien, dlaczego tak się dzieje (jakie są korzyści?), Ale kod mówi głośniej niż słowa!


0

String to jedna ze specjalnych klas, w której można je tworzyć bez nowej części Sring

to jest to samo co

int x = y;

lub

char c;


0

Zgodnie z podstawowym prawem ciągi znaków w java są niezmienne i uwzględniają wielkość liter.


0
 String str1 = "foo"; 
 String str2 = "foo"; 

Zarówno str1, jak i str2 należą do tego samego obiektu typu String, "foo", b'coz Java zarządza ciągami w StringPool, więc jeśli nowa zmienna odwołuje się do tego samego ciągu, nie tworzy kolejnej, a raczej przypisuje tę samą alerady obecną w StringPool .

 String str1 = new String("foo"); 
 String str2 = new String("foo");

Tutaj zarówno str1, jak i str2 należą do różnych obiektów, b'coz new String () na siłę tworzy nowy obiekt String.


-1

Java tworzy obiekt String dla każdego literału ciągu używanego w kodzie. Za każdym razem ""jest to to samo, co dzwonienie new String().

Łańcuchy to złożone dane, które po prostu „zachowują się” jak dane pierwotne. Literały łańcuchowe są w rzeczywistości obiektami, nawet jeśli udajemy, że są to literały prymitywne, jak 6, 6.0, 'c',itp. Zatem „literał” "text"String zwraca nowy obiekt String z wartością char[] value = {'t','e','x','t}. Dlatego dzwonię

new String("text"); 

jest właściwie podobne do dzwonienia

new String(new String(new char[]{'t','e','x','t'}));

Miejmy nadzieję, że stąd możesz zobaczyć, dlaczego twój podręcznik uważa to za zbyteczne.

Dla porównania, oto implementacja String: http://www.docjar.com/html/api/java/lang/String.java.html

To zabawna lektura, która może zainspirować do wglądu. Jest to również świetne dla początkujących do czytania i próbowania zrozumienia, ponieważ kod przedstawia kod bardzo profesjonalny i zgodny z konwencjami.

Kolejnym dobrym źródłem jest samouczek Java dotyczący Strings: http://docs.oracle.com/javase/tutorial/java/data/strings.html


Za każdym razem, gdy używany jest znak „”, jest to odniesienie do tego samego ciągu w stałej puli.
Markiz Lorne,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.