Warum können Sie in Java Strings mit dem Operator + hinzufügen, wenn String eine Klasse ist? Im String.java
Code habe ich keine Implementierung für diesen Operator gefunden. Verstößt dieses Konzept gegen die Objektorientierung?
Warum können Sie in Java Strings mit dem Operator + hinzufügen, wenn String eine Klasse ist? Im String.java
Code habe ich keine Implementierung für diesen Operator gefunden. Verstößt dieses Konzept gegen die Objektorientierung?
Antworten:
Schauen wir uns die folgenden einfachen Ausdrücke in Java an
int x=15;
String temp="x = "+x;
Der Compiler konvertiert "x = "+x;
in eine StringBuilder
interne und verwendet .append(int)
, um die Ganzzahl zur Zeichenfolge "hinzuzufügen".
Jeder Typ kann durch String-Konvertierung in den Typ String konvertiert werden.
Ein Wert x vom primitiven Typ T wird zuerst in einen Referenzwert konvertiert, als ob er als Argument für einen geeigneten Ausdruck zur Erstellung einer Klasseninstanz angegeben würde (§15.9):
- Wenn T boolesch ist, verwenden Sie den neuen Booleschen Wert (x).
- Wenn T char ist, verwenden Sie ein neues Zeichen (x).
- Wenn T Byte, Short oder Int ist, verwenden Sie die neue Ganzzahl (x).
- Wenn T lang ist, verwenden Sie neues Lang (x).
- Wenn T float ist, verwenden Sie new Float (x).
- Wenn T doppelt ist, verwenden Sie neues Double (x).
Dieser Referenzwert wird dann durch Zeichenfolgenkonvertierung in den Typ String konvertiert.
Jetzt müssen nur noch Referenzwerte berücksichtigt werden:
- Wenn die Referenz null ist, wird sie in die Zeichenfolge "null" konvertiert (vier ASCII-Zeichen n, u, l, l).
- Andernfalls wird die Konvertierung wie durch Aufrufen der toString-Methode des referenzierten Objekts ohne Argumente ausgeführt. Wenn das Ergebnis des Aufrufs der toString-Methode jedoch null ist, wird stattdessen die Zeichenfolge "null" verwendet.
Die toString-Methode wird durch die Urklasse Object (§4.3.2) definiert. Viele Klassen überschreiben es, insbesondere Boolean, Character, Integer, Long, Float, Double und String.
Siehe §5.4 für Details zum Kontext der Zeichenfolgenkonvertierung.
Optimierung der String-Verkettung: Eine Implementierung kann die Konvertierung und Verkettung in einem Schritt durchführen, um zu vermeiden, dass ein Zwischen-String-Objekt erstellt und anschließend verworfen wird. Um die Leistung der wiederholten Verkettung von Zeichenfolgen zu erhöhen, kann ein Java-Compiler die StringBuffer-Klasse oder eine ähnliche Technik verwenden, um die Anzahl der zwischengeschalteten Zeichenfolgenobjekte zu verringern, die durch Auswertung eines Ausdrucks erstellt werden.
Bei primitiven Typen kann eine Implementierung auch die Erstellung eines Wrapper-Objekts optimieren, indem sie direkt von einem primitiven Typ in eine Zeichenfolge konvertiert.
Die optimierte Version führt nicht zuerst eine vollständig umschlossene String-Konvertierung durch.
Dies ist ein gutes Beispiel für eine optimierte Version, die vom Compiler verwendet wird, allerdings ohne die Konvertierung eines Grundelements, wobei Sie sehen können, wie der Compiler im Hintergrund Dinge in einen StringBuilder ändert:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Dieser Java-Code:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
Erzeugt dies - sehen Sie, wie die beiden Verkettungsstile zu demselben Bytecode führen:
L0
LINENUMBER 23 L0
LDC "cip"
ASTORE 1
L1
LINENUMBER 24 L1
LDC "ciop"
ASTORE 2
// cip + ciop
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
// new StringBuilder(cip).append(ciop).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
Wenn Sie sich das obige Beispiel ansehen und sehen, wie der Bytecode basierend auf dem Quellcode im angegebenen Beispiel generiert wird, werden Sie feststellen, dass der Compiler die folgende Anweisung intern transformiert hat
cip+ciop;
in
new StringBuilder(cip).append(ciop).toString();
Mit anderen Worten, der Operator +
bei der Verkettung von Zeichenfolgen ist effektiv eine Abkürzung für die ausführlichere Sprache StringBuilder
.
Es ist eine Java-Compiler-Funktion, die die Operanden des +
Operators überprüft . Und basierend auf den Operanden generiert es den Bytecode:
Dies ist, was die Java-Spezifikation sagt :
Die Operatoren + und
-
werden als additive Operatoren bezeichnet. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionDie additiven Operatoren haben dieselbe Priorität und sind syntaktisch linksassoziativ (sie gruppieren von links nach rechts). Wenn der Typ eines der Operanden eines
+
Operators istString
, handelt es sich bei der Operation um eine Zeichenfolgenverkettung.Andernfalls muss der Typ jedes Operanden des
+
Operators ein Typ sein, der in einen primitiven numerischen Typ konvertierbar ist (§5.1.8), da sonst ein Fehler bei der Kompilierung auftritt.In jedem Fall muss der Typ jedes Operanden des Binäroperators
-
ein Typ sein, der in einen primitiven numerischen Typ konvertierbar ist (§5.1.8), da sonst ein Fehler bei der Kompilierung auftritt.
Wie überschreibt die String-Klasse den + Operator?
Das tut es nicht. Der Compiler macht es. Streng genommen ist der Compiler Überlastungen den Operator + für String - Operanden.
Zunächst wird (+) überladen und nicht überschrieben
Die Java-Sprache bietet spezielle Unterstützung für den String-Verkettungsoperator (+), der für Java-Strings-Objekte überladen wurde.
Wenn der linke Operand String ist, funktioniert er als Verkettung.
Wenn der linke Operand Integer ist, funktioniert er als Additionsoperator
int
und es gelten die normalen Regeln von Java.
Die Java-Sprache bietet spezielle Unterstützung für den String-Verkettungsoperator (+) und für die Konvertierung anderer Objekte in Strings. Die Verkettung von Zeichenfolgen wird über die Klasse StringBuilder
(oder StringBuffer
) und ihre append
Methode implementiert .
Die Bedeutung des +
Operators bei der Anwendung String
wird durch die Sprache definiert, wie jeder bereits geschrieben hat. Bedenken Sie Folgendes, da Sie dies nicht ausreichend überzeugend zu finden scheinen:
Ints, Floats und Doubles haben alle unterschiedliche binäre Darstellungen. Daher ist das Hinzufügen von zwei Ints in Bezug auf die Bitmanipulation eine andere Operation als das Hinzufügen von zwei Floats: Bei Ints können Sie Bit für Bit hinzufügen, ein Bit tragen und auf Überlauf prüfen. Für Floats müssen Sie die Mantissen und Exponenten separat behandeln.
Im Prinzip hängt "Addition" also von der Art der Objekte ab, die "hinzugefügt" werden. Java definiert es sowohl für Strings als auch für Ints und Floats (Longs, Doubles, ...).
Der +
Operator wird normalerweise durch eine StringBuilder
Kompilierungszeit ersetzt. Überprüfen Sie diese Antwort für weitere Details zu diesem Thema.
+
Bediener nicht durch ersetzt wird StringBuilder
?
+
Operator Plus ( ) ist eine Sprachfunktion von Java.