Perché in Java puoi aggiungere stringhe con l'operatore +, quando String è una classe? Nel String.java
codice non ho trovato alcuna implementazione per questo operatore. Questo concetto viola l'orientamento agli oggetti?
Perché in Java puoi aggiungere stringhe con l'operatore +, quando String è una classe? Nel String.java
codice non ho trovato alcuna implementazione per questo operatore. Questo concetto viola l'orientamento agli oggetti?
Risposte:
Diamo un'occhiata alle seguenti espressioni semplici in Java
int x=15;
String temp="x = "+x;
I convertiti compilatore "x = "+x;
in un StringBuilder
internamente ed usi .append(int)
a "aggiungere" il numero intero per la stringa.
5.1.11. Conversione di stringhe
Qualsiasi tipo può essere convertito in tipo String mediante conversione di stringhe.
Un valore x di tipo T primitivo viene prima convertito in un valore di riferimento come se dandolo come argomento a un'espressione di creazione di un'istanza di classe appropriata (§ 15.9):
- Se T è booleano, utilizzare il nuovo booleano (x).
- Se T è char, usa il nuovo carattere (x).
- Se T è byte, short o int, usa new Integer (x).
- Se T è lungo, usa il nuovo lungo (x).
- Se T è float, usa il nuovo float (x).
- Se T è doppio, utilizzare il nuovo doppio (x).
Questo valore di riferimento viene quindi convertito nel tipo String mediante la conversione di stringhe.
Ora devono essere considerati solo i valori di riferimento:
- Se il riferimento è null, viene convertito nella stringa "null" (quattro caratteri ASCII n, u, l, l).
- Altrimenti, la conversione viene eseguita come se invocasse il metodo toString dell'oggetto referenziato senza argomenti; ma se il risultato dell'invocazione del metodo toString è null, viene invece utilizzata la stringa "null".
Il metodo toString è definito dalla classe primordiale Object (§4.3.2). Molte classi lo sovrascrivono, in particolare Boolean, Character, Integer, Long, Float, Double e String.
Vedere §5.4 per dettagli sul contesto di conversione delle stringhe.
Ottimizzazione della concatenazione di stringhe: un'implementazione può scegliere di eseguire la conversione e la concatenazione in un solo passaggio per evitare di creare e scartare un oggetto String intermedio. Per aumentare le prestazioni della concatenazione di stringhe ripetute, un compilatore Java può utilizzare la classe StringBuffer o una tecnica simile per ridurre il numero di oggetti String intermedi creati dalla valutazione di un'espressione.
Per i tipi primitivi, un'implementazione può anche ottimizzare la creazione di un oggetto wrapper convertendo direttamente da un tipo primitivo in una stringa.
La versione ottimizzata in realtà non eseguirà prima una conversione String completamente chiusa.
Questa è una buona illustrazione di una versione ottimizzata utilizzata dal compilatore, anche se senza la conversione di una primitiva, in cui è possibile vedere il compilatore cambiare le cose in StringBuilder in background:
http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/
Questo codice java:
public static void main(String[] args) {
String cip = "cip";
String ciop = "ciop";
String plus = cip + ciop;
String build = new StringBuilder(cip).append(ciop).toString();
}
Genera questo - guarda come i due stili di concatenazione portano allo stesso bytecode:
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
Guardando l'esempio sopra e come viene generato il codice byte basato sul codice sorgente nell'esempio dato, si noterà che il compilatore ha trasformato internamente la seguente istruzione
cip+ciop;
in
new StringBuilder(cip).append(ciop).toString();
In altre parole, l'operatore +
nella concatenazione di stringhe è effettivamente una scorciatoia per il StringBuilder
linguaggio più dettagliato .
È la funzione del compilatore Java che controlla gli operandi +
dell'operatore. E in base agli operandi genera il codice byte:
Questo è ciò che dice la specifica Java :
Gli operatori + e
-
sono chiamati operatori additivi. AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpressionGli operatori additivi hanno la stessa precedenza e sono sintatticamente lasciati associativi (raggruppano da sinistra a destra). Se il tipo di uno degli operandi di un
+
operatore èString
, allora l'operazione è la concatenazione di stringhe.Altrimenti, il tipo di ciascuno degli operandi
+
dell'operatore deve essere un tipo convertibile (§5.1.8) in un tipo numerico primitivo, altrimenti si verifica un errore di compilazione.In ogni caso, il tipo di ciascuno degli operandi
-
dell'operatore binario deve essere un tipo convertibile (§5.1.8) in un tipo numerico primitivo, altrimenti si verifica un errore di compilazione.
In che modo la classe String ignora + operatore?
Non Il compilatore lo fa. A rigor di termini, il compilatore sovraccarica l'operatore + per gli operandi di stringa.
Innanzitutto (+) è sovraccarico, non sovrascritto
Il linguaggio Java fornisce un supporto speciale per l'operatore di concatenazione di stringhe (+), che è stato sovraccaricato per gli oggetti Java Strings.
Se l'operando sul lato sinistro è String, funziona come concatenazione.
Se l'operando sul lato sinistro è intero, funziona come operatore addizione
int
e quindi si applicano le normali regole di Java.
Il linguaggio Java fornisce un supporto speciale per l'operatore di concatenazione di stringhe (+) e per la conversione di altri oggetti in stringhe. La concatenazione di stringhe viene implementata tramite la classe StringBuilder
(o StringBuffer
) e il suo append
metodo.
Il significato +
dell'operatore quando applicato String
è definito dalla lingua, come tutti hanno già scritto. Dal momento che non ti sembra sufficientemente convincente, considera questo:
Ints, float e double hanno tutti differenti rappresentazioni binarie, e quindi aggiungere due ints è un'operazione diversa, in termini di manipolazione dei bit, rispetto all'aggiunta di due float: per gli ints puoi aggiungere bit per bit, portando un bit e controllando l'overflow; per i carri armati devi trattare separatamente le mante e gli esponenti.
Quindi, in linea di principio, "addizione" dipende dalla natura degli oggetti che vengono "aggiunti". Java lo definisce per stringhe, nonché ints e float (long, double, ...)
L' +
operatore viene di solito sostituito da a StringBuilder
in fase di compilazione. Controlla questa risposta per maggiori dettagli in merito.
+
operatore non è sostituito da StringBuilder
?
+
operatore Plus ( ) è la funzionalità linguistica di Java.