從java反編譯及字節(jié)碼角度探索分析String拼接字符串效率
前言
又刷到這篇文章
為什么idea建議去掉StringBuilder,使用“+”拼接字符串

網(wǎng)上有很多文章用 JUnit 進行測試驗證,可以網(wǎng)上搜一下,這里不做贅述。今天我們從反編譯和字節(jié)碼的角度分析字符串拼接的時候底層到底做了什么
拼接場景
示例 1:
public class Hello2 {
public static void main(String[] args) {
}
public void add1() {
String a = "aaa" + "bbb" + "ccc";
String b = new StringBuilder("aaa").append("bbb").append("ccc").toString();
}
}反編譯結(jié)果:
package com.noah.nowcoder;
public class Hello2 {
public static void main(String[] args) {}
public void add1() {
String a = "aaabbbccc";
String b = "aaa" + "bbb" + "ccc";
}
}Java 編譯器優(yōu)化(JDK 版本相關(guān)),編譯結(jié)果可以直接看出, String a = "aaa" + "bbb" + "ccc" 執(zhí)行效率更高;
示例 2:
public class Hello {
public static void main(String[] args) {
String str1 = "";
for (int i = 0; i < 100000; i++) {
str1 += "-" + UUID.randomUUID().toString();
}
System.out.println(str1);
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0; i < 100000; ++i) {
stringBuilder.append("-").append(UUID.randomUUID().toString());
}
System.out.println(stringBuilder.toString());
}
}反編譯結(jié)果:
package com.noah.nowcoder;
import java.util.UUID;
public class Hello {
public static void main(String[] args) {
String str1 = "";
for (int i = 0; i < 100000; i++)
str1 = str1 + "-" + UUID.randomUUID().toString();
System.out.println(str1);
StringBuilder stringBuilder = new StringBuilder();
for (int j = 0; j < 100000; j++)
stringBuilder.append("-").append(UUID.randomUUID().toString());
System.out.println(stringBuilder.toString());
}
}這一步結(jié)果不明顯
字節(jié)碼信息
接下來,我們看一下字節(jié)碼信息
Compiled from "Hello.java"
public class com.noah.nowcoder.Hello {
public com.noah.nowcoder.Hello();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: ldc #3 // int 100000
8: if_icmpge 46
11: new #4 // class java/lang/StringBuilder
14: dup
15: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
18: aload_1
19: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
22: ldc #7 // String -
24: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27: invokestatic #8 // Method java/util/UUID.randomUUID:()Ljava/util/UUID;
30: invokevirtual #9 // Method java/util/UUID.toString:()Ljava/lang/String;
33: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
39: astore_1
40: iinc 2, 1
43: goto 5
46: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
49: aload_1
50: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
53: new #4 // class java/lang/StringBuilder
56: dup
57: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
60: astore_2
61: iconst_0
62: istore_3
63: iload_3
64: ldc #3 // int 100000
66: if_icmpge 91
69: aload_2
70: ldc #7 // String -
72: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
75: invokestatic #8 // Method java/util/UUID.randomUUID:()Ljava/util/UUID;
78: invokevirtual #9 // Method java/util/UUID.toString:()Ljava/lang/String;
81: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
84: pop
85: iinc 3, 1
88: goto 63
91: getstatic #11 // Field java/lang/System.out:Ljava/io/PrintStream;
94: aload_2
95: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
98: invokevirtual #12 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
101: return
}注意:
15: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
調(diào)用了 StringBuilder 構(gòu)造函數(shù),初始化了一個 StringBuilder 對象(循環(huán)中初始化對象)
總結(jié)
根據(jù)字節(jié)碼改寫代碼
public void add2() {
String str1 = "";
for (int i = 0; i < 100000; i++) {
str1 += "-" + UUID.randomUUID().toString();
}
System.out.println(str1);
}
public void add3() {
String str1 = "";
for (int i = 0; i < 100000; i++) {
StringBuilder stringBuilder = new StringBuilder();
str1 = stringBuilder.append(str1).append("-").append(UUID.randomUUID().toString()).toString();
}
System.out.println(str1);
}字節(jié)碼文件:
public void add3();
Code:
0: ldc #10 // String
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: ldc #11 // int 100000
8: if_icmpge 48
11: new #3 // class java/lang/StringBuilder
14: dup
15: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V
18: astore_3
19: aload_3
20: aload_1
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: ldc #13 // String -
26: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
29: invokestatic #14 // Method java/util/UUID.randomUUID:()Ljava/util/UUID;
32: invokevirtual #15 // Method java/util/UUID.toString:()Ljava/lang/String;
35: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
41: astore_1
42: iinc 2, 1
45: goto 5
48: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream;
51: aload_1
52: invokevirtual #17 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
55: return從字節(jié)碼文件可以看出,add2() 和 add3() 基本上等價的。
所以循環(huán)中拼接字符串更高效的做法是將 StringBulider 放在循環(huán)外。
如下:
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
for (int j = 0; j < 100000; j++)
stringBuilder.append("-").append(UUID.randomUUID().toString());
System.out.println(stringBuilder.toString());
}以上就是從java反編譯及字節(jié)碼角度探索分析String拼接字符串效率的詳細內(nèi)容,更多關(guān)于java String拼接字符串效率的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java與JavaScript自動化測試Selenium使用詳解
這篇文章主要介紹了Java與JavaScript自動化測試Selenium的使用,Selenium是一個用于Web應用程序測試的工具,Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣,需要的朋友可以參考下2025-05-05
在SpringBoot下讀取自定義properties配置文件的方法
這篇文章主要介紹了在SpringBoot下讀取自定義properties配置文件的方法,文中涉及到了Spring-boot中讀取config配置文件的兩種方式,需要的朋友可以參考下2017-12-12
java微信開發(fā)API第三步 微信獲取以及保存接口調(diào)用憑證
這篇文章主要為大家詳細介紹了java微信開發(fā)API第二步,微信獲取以及保存接口調(diào)用憑證,感興趣的小伙伴們可以參考一下2016-06-06
詳解Java時區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat
這篇文章主要介紹了Java時區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat的區(qū)別于用法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07

