2012-05-04 5 views
5

Avevo una discussione sull'uso di String se StringBuffer s in Java. Quanti oggetti vengono creati in ciascuno di questi due esempi?Quanti oggetti vengono creati

Ex 1:

String s = "a"; 
s = s + "b"; 
s = s + "c";   

Es 2:

StringBuilder sb = new StringBuilder("a"); 
sb.append("b"); 
sb.append("c"); 

A mio parere, Ex 1 creerà 5 ed Ex 2 creerà 4 oggetti.

+2

Il primo esempio creerà 1 oggetto in quanto il compilatore può ottimizzarlo. –

+0

javac lo ottimizzerà? –

+1

L'esempio 1 genera questo: 'String s =" a "; s = (nuovo StringBuilder (String.valueOf (s))). Append ("b"). ToString(); s = (nuovo StringBuilder (String.valueOf (s))). Append ("c"). ToString(); System.err.println (s); '. Sembra che javac non lo stia ottimizzando (almeno in Java 6) –

risposta

4

È possibile determinare la risposta analizzando il codice byte java (utilizzare javap -c). L'esempio 1 crea due oggetti StringBuilder (vedere la riga n. 4) e due oggetti String (vedere la riga n. 7), mentre l'esempio 2 crea un oggetto StringBuilder (vedere la riga n. 2).

Si noti che è necessario prendere in considerazione anche gli oggetti char[] (poiché gli array sono oggetti in Java). Gli oggetti String e StringBuilder vengono entrambi implementati utilizzando uno char[] sottostante. Pertanto, l'esempio 1 crea otto oggetti e l'esempio 2 crea due oggetti.

Esempio 1:

public static void main(java.lang.String[]); 
    Code: 
    0: ldc    #2; //String a 
    2: astore_1 
    3: new    #3; //class java/lang/StringBuilder 
    6: dup 
    7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 
    10: aload_1 
    11: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    14: ldc    #6; //String b 
    16: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    19: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    22: astore_1 
    23: new    #3; //class java/lang/StringBuilder 
    26: dup 
    27: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V 
    30: aload_1 
    31: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    34: ldc    #8; //String c 
    36: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    39: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    42: astore_1 
    43: return 
} 

Esempio 2:

public static void main(java.lang.String[]); 
    Code: 
    0: new    #2; //class java/lang/StringBuilder 
    3: dup 
    4: ldc    #3; //String a 
    6: invokespecial #4; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 
    9: astore_1 
    10: aload_1 
    11: ldc    #5; //String b 
    13: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    16: pop 
    17: aload_1 
    18: ldc    #7; //String c 
    20: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    23: pop 
    24: return 
} 
+0

Ho un piccolo dubbio. , oracle docs qui http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html dice questo su append: "public StringBuilder append (Object obj) Aggiunge la stringa di rappresentazione del Argomento oggetto L'effetto complessivo è esattamente come se l'argomento fosse stato convertito in una stringa dal metodo String.valueOf (Object) ei caratteri di quella stringa venivano quindi aggiunti a questa sequenza di caratteri. " Non significa che gli oggetti verranno creati per i letterali String. –

5

In termini di oggetti creati:

Esempio 1 crea 8 oggetti:

String s = "a"; // No object created 
s = s + "b"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String) 
s = s + "c"; // 1 StringBuilder/StringBuffer + 1 String + 2 char[] (1 for SB and 1 for String) 

Esempio 2 crea 2 oggetto:

StringBuffer sb = new StringBuffer("a"); // 1 StringBuffer + 1 char[] (in SB) 
sb.append("b"); // 0 
sb.append("c"); // 0 

per essere onesti, non sapevo che il nuovo char [] in realtà ha creato un oggetto in Java (ma sapevo che erano stati creati). Grazie a aix per averlo indicato.

+0

Downvoter ti piacerebbe fornire la tua opinione? –

+0

Lui/lei avrei potuto eseguire la procedura di test in un'altra versione JDK e ottenere risultati diversi. –

5

ho usato un profiler di memoria per ottenere i conteggi esatti.

Sulla mia macchina, il primo esempio crea 8 oggetti:

String s = "a"; 
s = s + "b"; 
s = s + "c"; 
  • due oggetti di tipo String;
  • due oggetti di tipo StringBuilder;
  • quattro oggetti di tipo char[].

D'altra parte, il secondo esempio:

StringBuffer sb = new StringBuffer("a"); 
sb.append("b"); 
sb.append("c"); 

crea 2 oggetti:

  • un oggetto di tipo StringBuilder;
  • un oggetto di tipo char[].

Questo sta utilizzando JDK 1.6u30.

P.S. Per rendere il confronto equo, probabilmente dovresti chiamare sb.toString() alla fine del secondo esempio.

+0

è dipendente dalla macchina/dal compilatore? –

+0

@AlexLockwood: Probabilmente JDK-dipendente in una certa misura, anche se sarei piuttosto sorpreso se ci fosse molta variabilità tra i recenti JDK. – NPE

+0

Sembra piuttosto sciocco distinguere tra un 'char []' e l'astrazione 'String' in un linguaggio di alto livello come Java: P. Ma sono d'accordo che sia corretto farlo (non stupido da parte tua ... solo sciocco in una specie di stupido esempio come questo). –

-1

La risposta è legata a specifiche implementazioni del linguaggio (librerie di compilazione e runtime). Anche alla presenza di opzioni di ottimizzazione specifiche o meno. E, naturalmente, versione dell'implementazione (e, implicitamente, la JLS è compatibile con). Quindi, è meglio parlare in termini di minimi e massimi. In effetti, questo esercizio dà una migliore

Per Ex1, il numero minimo di oggetti è 1 (il compilatore si rende conto che ci sono solo costanti coinvolte e produce solo il codice per String s= "abc" ;). Il massimo potrebbe essere qualsiasi cosa, a seconda dell'implementazione, ma una stima ragionevole è 8 (dato anche in un'altra risposta come il numero prodotto da una determinata configurazione).

Per Ex2, il numero minimo di oggetti è 2. Il compilatore non ha modo di sapere se abbiamo sostituito StringBuilder con una versione personalizzata con semantica diversa, quindi non ottimizzerà. Il massimo potrebbe essere intorno a 6, per un'implementazione StringBuilder estremamente ricca di memoria che espande un array di supporto char[] un carattere alla volta, ma nella maggior parte dei casi sarà anche 2.

+0

Il compilatore 'produce il codice per 'String s =" abc ";'', ma questo non crea un oggetto quando viene eseguito, quindi il minimo è effettivamente zero. – EJP