Il "vecchio" modo produce un mucchio di StringBuilder
operazioni orientate. Considera questo programma:
public class Example {
public static void main(String[] args)
{
String result = args[0] + "-" + args[1] + "-" + args[2];
System.out.println(result);
}
}
Se lo compiliamo con JDK 8 o precedente e poi usiamo javap -c Example
per vedere il bytecode, vediamo qualcosa del genere:
esempio di classe pubblica {
public Example ();
Codice:
0: aload_0
1: invokespecial # 1 // Metodo java / lang / Object. "<init>" :() V
4: ritorno
public static void main (java.lang.String []);
Codice:
0: nuovo # 2 // classe java / lang / StringBuilder
3: dup
4: invokespecial # 3 // Metodo java / lang / StringBuilder. "<init>" :() V
7: aload_0
8: iconst_0
9: aaload
10: invokevirtual # 4 // Metodo java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
13: ldc # 5 // String -
15: invokevirtual # 4 // Metodo java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
18: aload_0
19: iconst_1
20: aaload
21: invokevirtual # 4 // Metodo java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
24: ldc # 5 // String -
26: invokevirtual # 4 // Metodo java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
29: aload_0
30: iconst_2
31: aaload
32: invokevirtual # 4 // Metodo java / lang / StringBuilder.append: (Ljava / lang / String;) Ljava / lang / StringBuilder;
35: invokevirtual # 6 // Metodo java / lang / StringBuilder.toString :() Ljava / lang / String;
38: astore_1
39: getstatic # 7 // Campo java / lang / System.out: Ljava / io / PrintStream;
42: aload_1
43: invokevirtual # 8 // Metodo java / io / PrintStream.println: (Ljava / lang / String;) V
46: ritorno
}
Come puoi vedere, crea un file StringBuilder
e usa append
. Questo è famoso abbastanza inefficiente poiché la capacità predefinita del buffer integrato StringBuilder
è di soli 16 caratteri, e non c'è modo per il compilatore di sapere di allocare di più in anticipo, quindi finisce per dover riallocare. È anche un mucchio di chiamate di metodo. (Si noti che la JVM a volte può rilevare e riscrivere questi modelli di chiamate per renderli più efficienti, però.)
Diamo un'occhiata a cosa genera Java 9:
esempio di classe pubblica {
public Example ();
Codice:
0: aload_0
1: invokespecial # 1 // Metodo java / lang / Object. "<init>" :() V
4: ritorno
public static void main (java.lang.String []);
Codice:
0: aload_0
1: iconst_0
2: aaload
3: aload_0
4: iconst_1
5: aaload
6: aload_0
7: iconst_2
8: aaload
9: invokedynamic # 2, 0 // InvokeDynamic # 0: makeConcatWithConstants: (Ljava / lang / String; Ljava / lang / String; Ljava / lang / String;) Ljava / lang / String;
14: astore_1
15: getstatic # 3 // Campo java / lang / System.out: Ljava / io / PrintStream;
18: aload_1
19: invokevirtual # 4 // Metodo java / io / PrintStream.println: (Ljava / lang / String;) V
22: ritorno
}
Oh mio ma è più breve. :-) Fa una singola chiamata a makeConcatWithConstants
from StringConcatFactory
, che dice questo nel suo Javadoc:
Metodi per facilitare la creazione di metodi di concatenazione di stringhe, che possono essere utilizzati per concatenare in modo efficiente un numero noto di argomenti di tipi noti, possibilmente dopo l'adattamento del tipo e la valutazione parziale degli argomenti. Questi metodi vengono generalmente utilizzati come metodi di bootstrap per i invokedynamic
siti di chiamata, per supportare la funzione di concatenazione di stringhe del linguaggio di programmazione Java.