2015-09-22 7 views
35

String ist ein Spezialfall in Java. Es ist eine Klasse, die ich in der source code untersuchen kann, aber es hat auch seinen eigenen Infix-Operator +, der syntaktischer Zucker für StringBuilder zu sein scheint.Wo ist `+` für Strings im Java-Quellcode implementiert?

Zum Beispiel

"Hello " + yourName; 

new StringBuilder().append("Hello ").append(yourName).toString(); 

Es gibt keine benutzerdefinierten Operatoren in Java werden könnte, also wo ist + für String angegeben?

Könnte derselbe Mechanismus verwendet werden, um zusätzliche Operatoren zu erstellen, z. B. für Vektoren?

+0

Nein. Es konnte nicht. –

+6

Wo ist '+' für 'int' angegeben? – gronostaj

+0

@gronostaj - '+' wird vom Compiler ebenfalls erkannt. 'int i = 2 + 3' wird durch 'int i = 5' ersetzt. Falls der Wert von int zur Kompilierzeit nicht bestimmt werden kann, gibt es Anweisungen wie "iadd", die anstelle von "+" – TheLostMind

Antwort

44

+ ist implementiert in Java Compiler. Der Compiler ersetztString + String mit entweder Kompilierzeit Konstanten oder StringBuilder Code. Beachten Sie, dass dies auch für Primitive gilt. d. h., int i=1+2 könnte während der Kompilierung direkt zu int i=3 ersetzt werden.

+2

Haben Sie eine Verbindung zur Compiler-Quelle, wo dies geschieht? – sdgfsdh

+2

@sdgfsdh - Ich könnte Ihnen Byte-Code zeigen. Würde das genügen? Sie werden sehen können, dass '+' NICHT als Teil des Byte-Codes geht – TheLostMind

+0

Ich stimme der obigen Antwort zu und möchte auch hinzufügen, dass '+' nicht Syntax Zucker für StringBuilder ist. Wenn Sie StringBuilder verwenden, können Sie nicht viele String-Objekte erstellen. Falls Sie '+' verwenden, ist jeder Zusatz ein neues String-Objekt. – jokernoel

8

Java-Compiler haben die Implementierung für +. Die Javadocs sagt:

Die Java-Sprache spezielle Unterstützung für die Zeichenfolge Verkettungsoperator (+), und für die Umwandlung von anderen Objekten zu Strings zur Verfügung stellt. String-Verkettung wird durch die StringBuilder (oder StringBuffer) -Klasse und ihre Append-Methode implementiert. Zeichenfolge Konvertierungen werden über die Methode toString implementiert, die von Object definiert und von allen Klassen in Java übernommen wird. Weitere Informationen zur Zeichenfolgenverkettung und -konvertierung finden Sie in den Abschnitten unter Gosling, Joy, und Steele, der Java-Sprachspezifikation.

können Sie versuchen, dies zu überprüfen:

public static void main(String[] args) { 
    String s1 = "s1"; 
    String s2 = "s2"; 
    String s3 = s1 + s2; 
    String s4 = new StringBuilder(s1).append(s2).toString(); 
} 

Der obige Code erzeugt den gleichen Bytecode für + und bei der Verwendung von String:

L0 
LINENUMBER 23 L0 
LDC "s1" 
ASTORE 1 

L1 
LINENUMBER 24 L1 
LDC "s2" 
ASTORE 2 

// s3 = s1 + s2 

L2 
LINENUMBER 25 L2 

NEW java/lang/StringBuilder 
DUP 
ALOAD 1 
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String; 
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V 
ALOAD 2 
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder; 
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String; 

ASTORE 3 

// s4 = new StringBuilder(s1).append(s2).toString() 

L3 
LINENUMBER 26 L3 

NEW java/lang/StringBuilder 
DUP 
ALOAD 1 
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V 
ALOAD 2 
INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder; 
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String; 

ASTORE 4 
L4 
LINENUMBER 27 L4 
RETURN 
23

Sie können mit der Spezifikation überprüfen. Der Compiler hat die Implementierung, nicht den Java-Quellcode.

Java Language Specification- 15.18.1. String Concatenation Operator +

Ein Implementierung Umwandlung und Verkettung kann wählen, in einem Schritt durchzuführen, zu vermeiden, zu schaffen, und dann ein Zwischen String-Objekt verworfen wird. Um die Leistung wiederholter Zeichenfolgenverkettung zu erhöhen, kann ein Java-Compiler die StringBuffer-Klasse oder eine ähnliche Technik verwenden, um die Anzahl der zwischengeordneten String-Objekte zu reduzieren, die durch Auswertung eines Ausdrucks erstellt werden.

Es zeigt den Beweis, dass die Implementierung vom Compiler abhängt.

+1

Ja. * Java Compiler kann * verwenden .. Aber die meisten Compiler tun. :) – TheLostMind

5

Während derzeit die meisten Java-Compiler StringBuilder Kette verwenden, ist es nicht angegeben, dass es immer auf diese Weise sein sollte. Insbesondere gibt es eine proposal, um dies drastisch zu ändern in Java-9 durch einzelne ersetzen invokedynamic Aufruf und Einführung neuer Metafactory, die eine geeignete MethodHandle in Laufzeit generieren, um Verkettung durchzuführen.

+0

Ich frage mich, warum Java nicht statische Verkettungsmethoden, die zwei, drei oder vier 'String' Instanzen nehmen, und auch eine, die nimmt oder sonst eine' string [] ', und auf jeden Fall eine neue Zeichenfolge zurückgibt, die die enthält Verkettung aller Strings in Frage? Solche Funktionen könnten in jedem Fall effizienter sein als Code, der tatsächlich 'StringBuilder' verwendet. Der einzige Weg, "StringBuilder" so zu sehen, dass er sogar im entferntesten vernünftig ist, wäre, wenn die meisten Versionen des JIT-Gucklochs bestimmte Benutzungsmuster optimieren, um interne Funktionen des angegebenen Formulars aufzurufen. – supercat

+0

@supercat, suchen Sie ['String.join (" ", String ...)'] (http://docs.oracle.com/javase/8/docs/api/java/lang/Zeichenkette.html # join.lang.CharSequence-java.lang.CharSequence ...-)? Beachten Sie, dass 'StringBuilder' nicht nur Strings akzeptieren kann, sondern auch primitive Werte wie' int', 'double',' boolean' und so weiter. Und während der String-Verkettung werden sie nicht eingerahmt, noch werden separate Strings erzeugt: ihre Werte werden direkt in den Puffer verkettet. Wie würden Sie sich vorstellen, dies mit statischen Methoden zu lösen? Die Anzahl der möglichen Kombinationen ist zu groß. –

+0

War "beitreten" eine spätere Ausgabe? Meine Java-lib-Quelle hat es nicht. Die Verwendung von StringBuilder erzeugt garantiert eine Menge an Müll, der größer ist als die Gesamtlänge der erzeugten Zeichenfolge. Für das Szenario, in dem alle Dinge, die verkettet werden, Zahlen sind, könnte es etwas vor 'String.join (ding1.toString(), ding2.toString() usw.) liegen ', aber nicht viel. – supercat

1

Wie für die Sprache, nein, es ist nicht erweiterbar. Dies ist ein spezifisches Verhalten, keine andere Klasse erweitert den Operator +.

Was wo dies geschehen ist, suchen Sie nach string_add (not a real JVM op) in den folgenden Dateien:


Wie, warum, Java sollte um einfach zu sein, oder zumindest einfacher als C++ und ab asic Sache wie String-Manipulation war eine Art Pflicht. Eine Überladung des Operators würde jedoch die Komplexität erhöhen.

Verwandte Themen