2010-02-24 10 views
7

Kilka minut temu zobaczyłem this question i zdecydowałem się rzucić okiem na klasę String języka Java, aby sprawdzić, czy nastąpiło przeciążenie dla operatora +.+ operator dla String w Javie

nie mogłem znaleźć nic, ale wiem, że mogę to zrobić

String ab = "ab"; 
String cd = "cd"; 
String both = ab + cd; //both = "abcd" 

Gdzie ten realizowany?

Odpowiedz

12

Z Fine Manual:

języku Java zapewnia specjalne wsparcie dla operatora konkatenacji (+), a do przeliczenia innych obiektów do strun. Łączenie ciągów jest realizowane za pośrednictwem klasy StringBuilder (lub StringBuffer) i jej metody append. Konwersje łańcuchowe są realizowane za pomocą metody toString, zdefiniowanej przez obiekt i dziedziczone przez wszystkie klasy w języku Java. Aby uzyskać dodatkowe informacje dotyczące konkatenacji i konwersji ciągów, zobacz Gosling, Joy i Steele, Specyfikacja języka Java.

Zobacz String Concatenation w JLS.

+0

'StringBuilder' powinien być preferowany tam, gdzie synchronizacja nie jest problemem. – gpampara

+0

@gpampara Kompilator wie, jak używać StringBuilder. StringBuffer był używany w starych wydaniach przed wprowadzeniem StringBuilder. –

2

Jest obsługiwane przez kompilator.

+1

Imponująca odpowiedź. Czy rozważałeś bycie nauczycielem? – whiskeysierra

+0

@Willi Schönborn: Cóż, to jest prosta i prawidłowa odpowiedź. Nie miałem czasu napisać więcej, kiedy to napisałem, a kiedy wróciłem do komputera, było mnóstwo odpowiedzi wyjaśniających go bardziej szczegółowo. Przykro mi to mówić, ale nie widzę sensu w duplikowaniu innych odpowiedzi, polecam czytanie @ Seana i @ jleedev'a, jeśli potrzebujesz więcej informacji (I tak, nauczanie jest w moim CV). – Fredrik

+0

Chodzi o to: Twoja odpowiedź jest tak ogólna, że ​​pasuje prawie do 75% wszystkich pytań związanych z językiem SO na temat SO. – whiskeysierra

2

To jest szczególne zachowanie udokumentowane w language specification.

15.18.1 konkatenacji Operator +

Jeśli tylko jedno wyrażenie operand jest typu String, a następnie konwersja ciąg jest wykonywane na drugim argumencie do wytwarzają ciąg w czasie wykonywania. wynik jest odniesienie do obiektu (ciąg nowo utworzone, jeżeli ekspresja jest kompilacji stałą wyrażenie (§15.28)), który jest połączeniem tych dwóch operandów łańcuchów. Znaki lewego operandu poprzedzają znaki prawostronnego operandu w nowo utworzonym łańcuchu znaków. Jeśli operand typu String ma wartość null, to ciąg "zerowy" jest używany zamiast tego argumentu.

7

Kompilator traktuje swój kod tak, jakby trzeba było napisane coś takiego:

String both = new StringBuilder().append(ab).append(cd).toString(); 

EDIT: Wszelkie odniesienia? Cóż, jeśli skompiluję i zdekompiluję kod OP, otrzymuję:

0: ldC#2; //String ab 
2: astore_1 
3: ldC#3; //String cd 
5: astore_2 
6: new #4; //class java/lang/StringBuilder 
9: dup 
10: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V 
13: aload_1 
14: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
17: aload_2 
18: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
21: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
24: astore_3 
25: return 

Tak, to jest tak jak powiedziałem.

+1

wszelkie odniesienia do tego? –

0

String jest zdefiniowany jako standardowy typ, taki jak int, double, float itp. Na poziomie kompilatora. Zasadniczo wszystkie kompilatory mają przeciążenie operatora. Przeciążanie operatorów nie jest zdefiniowane dla programistów (inaczej niż w C++).

Co ciekawe: To pytanie zostało zalogowany jako błąd: http://bugs.sun.com/view_bug.do?bug_id=4905919

2

Większość tutaj odpowiedzi są poprawne (nie jest to obsługiwane przez kompilator, + przekształca się .append() ...)

Chciałem dodać, że każdy powinien rzucić okiem na kod źródłowy do String i dołączyć w pewnym momencie, to całkiem imponujące.

Uważam, że przyszedł, aby coś takiego:

"a"+"b"+"c" 

=

new String().append("a").append("b").append("c") 

Ale wtedy niektóre magia dzieje. Ten zamienia się:

  • Utwórz tablicę ciągów o długości 3
  • skopiować do pierwszej pozycji.
  • kopia b do drugiego
  • kopii C do trzeciego

Podczas gdy większość ludzi wierzy, że będzie tworzyć „AB”, a następnie wyrzucić, gdy tworzy „ABC”. Rozumie, że jest przykuty i manipuluje.

Istnieje również sztuczka, w której jeśli masz ciąg "abc" i pytasz o podciąg, który okazuje się być "bc", mogą one współdzielić tę samą bazową tablicę. Zauważysz, że istnieje pozycja początkowa, pozycja końcowa i flaga "udostępniona".

W rzeczywistości, jeśli nie jest wspólna, to możliwe jest, aby przedłużyć długość łańcucha i kopiować innych w.

Teraz jestem po prostu mylące. Przeczytaj kod źródłowy - jest całkiem fajny.

+1

Nie ma "nowego ciągu(). Append (" a "). Append (" b "). Append (" c ")', ale 'nowy StringBuilder(). Append (" a "). Append (" b) .append ("c"). toString() '. * No-Stringbuilder * sposób byłby' "a" .concat ("b"). concat ("c") ', i to jest nieefektywny sposób jak opisałeś (ale gdy używasz + ze stałymi w czasie kompilacji, wszystko to jest już robione przez kompilator.) –