[英]Appending Strings in Java/C# without using StringBuffer.Append or StringBuilder.Append
[英]Does the compiler optimize Stringbuffer/StringBuilder.append() for constant strings?
我讀了Jon Skeet關於用+連接字符串的答案 。 我想知道編譯器是否還使用StringBuffer / StringBuilder識別附加的constand字符串。
這個構建URL的代碼有一個好的意圖:
StringBuffer sb = new StringBuffer(constant1);
sb.append(nonconstant);
sb.append("?");
sb.append(constant2);
sb.append("=");
sb.append(constant3);
sb.append("&");
sb.append(constant4);
sb.append("=");
sb.append(constant5);
但是,如果編譯器沒有為常量優化Stringbuffer.append(),我會說以下代碼會更有效:
StringBuffer sb = new StringBuffer(constant1);
sb.append(non-constant);
sb.append("?" + constant2 + "=" + constant3 + "&" + constant4 + "=" + constant5);
因為編譯器會在編譯時優化+
字符串連接。
為什么不嘗試一下呢? 在java 1.7中,以下類的主要方法:
public class Concat1 { private static final String constant2 = "c2"; private static final String constant3 = "c3"; public void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append(args[0]); sb.append("?"); sb.append(constant2); sb.append("="); sb.append(constant3); System.out.println(sb.toString()); } }
(為了清晰起見,我更改了常量的數量)產生以下字節代碼:
public class Concat1 { public Concat1(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public void main(java.lang.String[]); Code: 0: new #2 // class java/lang/StringBuilder 3: dup 4: invokespecial #3 // Method java/lang/StringBuilder."":()V 7: astore_2 8: aload_2 9: aload_1 10: iconst_0 11: aaload 12: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: pop 16: aload_2 17: ldc #5 // String ? 19: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: pop 23: aload_2 24: ldc #6 // String c2 26: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 29: pop 30: aload_2 31: ldc #7 // String = 33: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 36: pop 37: aload_2 38: ldc #8 // String c3 40: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 43: pop 44: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream; 47: aload_2 48: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 51: invokevirtual #11 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 54: return }
而以下課程:
public class Concat2 { private static final String constant2 = "c2"; private static final String constant3 = "c3"; public void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append(args[0]); sb.append("?" + constant2 + "=" + constant3); System.out.println(sb.toString()); } }
編譯為:
public class Concat2 { public Concat2(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public void main(java.lang.String[]); Code: 0: new #2 // class java/lang/StringBuilder 3: dup 4: invokespecial #3 // Method java/lang/StringBuilder."":()V 7: astore_2 8: aload_2 9: aload_1 10: iconst_0 11: aaload 12: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: pop 16: aload_2 17: ldc #5 // String ?c2=c3 19: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 22: pop 23: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream; 26: aload_2 27: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 30: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 33: return }
顯然,你是對的。 在第二個類中, StringBuilder
的append方法只被調用兩次,而在第一個例子中,它被調用每個常量字符串。
編譯器是否針對常量字符串優化Stringbuffer / StringBuilder.append()?
沒有。
但是,我認為您提出的優化的前提是不正確的。 我建議您使用兩個版本的代碼並編譯它們。 然后使用javap
查看編譯代碼在每種情況下的樣子。
(FWIW,我希望你的“優化”不會改進生成的代碼。它很可能會創建第二個StringBuilder
來連接中間字符串,並將其轉換為String。你最終會有大致相同數量的append
操作,另外還創建了一個額外的臨時StringBuilder和一個額外的臨時String。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.