2015-09-22 16 views
35

String è un caso speciale in Java. È una classe, che posso esaminare nel source code, ma ha anche il proprio operatore infisso +, che sembra essere zucchero sintattico per StringBuilder.Dove è implementato `+` per le stringhe nel codice sorgente Java?

Per esempio,

"Hello " + yourName; 

potrebbe diventare

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

ci sono gli operatori definiti dall'utente in Java, quindi dove si + specificati per String?

È possibile utilizzare lo stesso meccanismo per creare operatori aggiuntivi, ad esempio per vettori?

+0

No. Non poteva. –

+6

Dove è specificato '+' per 'int'? – gronostaj

+0

@gronostaj - '+' è riconosciuto anche dal compilatore. 'int i = 2 + 3' sarà sostituito da' int i = 5'. Nel caso in cui il valore di int non possa essere determinato in fase di compilazione, allora ci sono istruzioni come 'iadd' che sono usate al posto di' + ' – TheLostMind

risposta

44

+ è implementato in java compilatori. Il compilatore sostituisceString + String con tempo di compilazione costanti o codice StringBuilder. Si noti che questo vale anche per le primitive . Ad esempio, int i=1+2 potrebbe essere sostituito direttamente in int i=3 durante la compilazione stessa.

+2

Hai un link alla sorgente del compilatore dove questo accade? – sdgfsdh

+2

@sdgfsdh - Potrei mostrarti il ​​codice byte. Sarebbe sufficiente? Sarete in grado di vedere che '+' NON sta andando come parte del byte code – TheLostMind

+0

Sono d'accordo con la risposta sopra e voglio anche aggiungere che '+' non è lo zucchero di sintassi per StringBuilder. Quando usi StringBuilder, questo non consente di creare molti oggetti String. Nel caso in cui si usi '+' ogni aggiunta è un nuovo oggetto String. – jokernoel

8

I compilatori Java hanno l'implementazione per +. Il Javadocs dice:

linguaggio Java fornisce un supporto speciale per la stringa operatore di concatenazione (+), e per la conversione di altri oggetti per stringhe. La concatenazione di stringhe viene implementata tramite la classe StringBuilder (o StringBuffer) e il relativo metodo append. Stringa Le conversioni vengono implementate tramite il metodo toString, definito dall'oggetto e ereditato da tutte le classi in Java. Per ulteriori informazioni su sulla concatenazione di stringhe e sulla conversione, vedere Gosling, Joy, e Steele, The Java Language Specification.

Si può cercare di controllare questo:

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

Il codice precedente genera lo stesso bytecode + e quando si utilizza StringBuilder:

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

È possibile controllare con la specifica. Il compilatore ha l'implementazione di esso, non il codice sorgente Java.

Java Language Specification- 15.18.1. String Concatenation Operator +

L'attuazione può scegliere di eseguire la conversione e la concatenazione in un solo passo per evitare di creare e poi rimuovere l'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.

Mostra la prova che l'implementazione dipende dal compilatore.

+1

Sì. * il compilatore java può usare * .. Ma la maggior parte dei compilatori lo fa. :) – TheLostMind

5

Mentre attualmente la maggior parte dei compilatori Java utilizza la catena StringBuilder, non è specificato che dovrebbe essere sempre in questo modo. In particolare c'è un proposal per cambiare drasticamente questo in Java-9 sostituendo con una singola chiamata invokedynamic e introducendo un nuovo metafactory che genererà un appropriato MethodHandle in runtime per eseguire la concatenazione.

+0

Mi chiedo perché Java non usi i metodi di concatenazione statica che prendono due, tre o quattro istanze 'String', e anche uno che prende o un' string [] ', e in ogni caso restituisce una nuova stringa contenente il concatenazione di tutte le stringhe in questione? Tali funzioni potrebbero essere in ogni caso più efficienti del codice che utilizza effettivamente 'StringBuilder'. L'unico modo in cui posso vedere 'StringBuilder' come ragionevole anche da remoto sarebbe se la maggior parte delle versioni del peep-hole JIT ottimizza determinati schemi di utilizzo per richiamare le funzioni interne del modulo indicato. – supercat

+0

@supercat, stai cercando ['String.join (" ", String ...)'] (http://docs.oracle.com/JavaSE/8/docs/api/java/lang/String.html # join-java.lang.CharSequence-java.lang.CharSequence ...-)? Si noti che 'StringBuilder' può accettare non solo stringhe, ma valori primitivi come' int', 'double',' boolean' e così via. E durante la concatenazione di stringhe non sono boxed, né vengono create stringhe separate: i loro valori vengono concatenati direttamente nel buffer. Come immaginereste di risolvere questo problema con metodi statici? Il numero di combinazioni possibili è troppo grande. –

+0

"Unirsi" a un'edizione successiva? La mia sorgente lib Java non ce l'ha. L'uso di StringBuilder è garantito per generare una quantità di spazzatura maggiore della lunghezza totale della stringa creata. Per lo scenario in cui tutte le cose concatenate erano numeri, potrebbe finire leggermente prima di 'String.join (thing1.toString(), thing2.toString(), ecc.)', Ma non di molto. – supercat

1

Per quanto riguarda la lingua, no, non è estensibile. Questo è un comportamento specifico, nessun'altra classe estende l'operatore +.

Quanto a che non si proceda, cercare string_add (not a real JVM op) nei seguenti file:


Quanto al perché, Java è stato supposto per essere semplici, o almeno più semplici di C++ e ab la cosa asica come la manipolazione delle stringhe era obbligatoria. Tuttavia, l'overloading dell'operatore aggiungerebbe complessità.