從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 Apache Shiro安全框架快速開發(fā)詳解流程
Apache Shiro是一個強大且易用的Java安全框架,執(zhí)行身份驗證、授權(quán)、密碼和會話管理。使用Shiro的易于理解的API,您可以快速、輕松地獲得任何應(yīng)用程序,從最小的移動應(yīng)用程序到最大的網(wǎng)絡(luò)和企業(yè)應(yīng)用程序2021-10-10
SpringBoot2零基礎(chǔ)到精通之JUnit 5與指標監(jiān)控
SpringBoot是一種整合Spring技術(shù)棧的方式(或者說是框架),同時也是簡化Spring的一種快速開發(fā)的腳手架,本篇讓我們一起學習JUnit 5與指標監(jiān)控2022-03-03
Java使用TCP實現(xiàn)數(shù)據(jù)傳輸實例詳解
這篇文章主要介紹了Java使用TCP實現(xiàn)數(shù)據(jù)傳輸實例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06

