为了验证编译器对于String相关代码的字节码优化,我简单的做了个测试:
jdk版本:1.7.0_51
java 用例代码:
package com.rsp.shiro; /** * Created by cd_huang on 2017/4/1. */ public class StringTest { public static String StaticString(){ return "BBB"; } public static String getString1(){ return "AAA"+"BBB"; } public static String getString2(){ return new StringBuilder().append("AAA").append("BBB").toString(); } public static String getString3(){ return "AAA"+StaticString(); } public static String getString4(){ return new StringBuilder().append("AAA").append(StaticString()).toString(); } }
命令行输入:C:\Users\hcd>javac c:\StringTest.java
生成StringTest.class文件。
命令行输入:C:\Users\hcd>javap -v c:\StringTest.class
生成java编译后的字节码指令。
Classfile /c:/StringTest.class Last modified 2017-4-1; size 721 bytes MD5 checksum 60b413955d7484157009f74a40848d59 Compiled from "StringTest.java" public class com.rsp.shiro.StringTest SourceFile: "StringTest.java" minor version: 0 major version: 51 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Methodref #11.#24 // java/lang/Object."<init>":()V #2 = String #25 // BBB #3 = String #26 // AAABBB #4 = Class #27 // java/lang/StringBuilder #5 = Methodref #4.#24 // java/lang/StringBuilder."<init>":( )V #6 = String #28 // AAA #7 = Methodref #4.#29 // java/lang/StringBuilder.append:(Lj ava/lang/String;)Ljava/lang/StringBuilder; #8 = Methodref #4.#30 // java/lang/StringBuilder.toString:( )Ljava/lang/String; #9 = Methodref #10.#31 // com/rsp/shiro/StringTest.StaticStr ing:()Ljava/lang/String; #10 = Class #32 // com/rsp/shiro/StringTest #11 = Class #33 // java/lang/Object #12 = Utf8 <init> #13 = Utf8 ()V #14 = Utf8 Code #15 = Utf8 LineNumberTable #16 = Utf8 StaticString #17 = Utf8 ()Ljava/lang/String; #18 = Utf8 getString1 #19 = Utf8 getString2 #20 = Utf8 getString3 #21 = Utf8 getString4 #22 = Utf8 SourceFile #23 = Utf8 StringTest.java #24 = NameAndType #12:#13 // "<init>":()V #25 = Utf8 BBB #26 = Utf8 AAABBB #27 = Utf8 java/lang/StringBuilder #28 = Utf8 AAA #29 = NameAndType #34:#35 // append:(Ljava/lang/String;)Ljava/l ang/StringBuilder; #30 = NameAndType #36:#17 // toString:()Ljava/lang/String; #31 = NameAndType #16:#17 // StaticString:()Ljava/lang/String; #32 = Utf8 com/rsp/shiro/StringTest #33 = Utf8 java/lang/Object #34 = Utf8 append #35 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder; #36 = Utf8 toString { public com.rsp.shiro.StringTest(); flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init> ":()V 4: return LineNumberTable: line 6: 0 public static java.lang.String StaticString(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #2 // String BBB 2: areturn LineNumberTable: line 8: 0 public static java.lang.String getString1(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=0, args_size=0 0: ldc #3 // String AAABBB 2: areturn LineNumberTable: line 11: 0 public static java.lang.String getString2(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=0, args_size=0 0: new #4 // class java/lang/StringBuilder 3: dup 4: invokespecial #5 // Method java/lang/StringBuilder. "<init>":()V 7: ldc #6 // String AAA 9: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: ldc #2 // String BBB 14: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 17: invokevirtual #8 // Method java/lang/StringBuilder. toString:()Ljava/lang/String; 20: areturn LineNumberTable: line 14: 0 public static java.lang.String getString3(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=0, args_size=0 0: new #4 // class java/lang/StringBuilder 3: dup 4: invokespecial #5 // Method java/lang/StringBuilder. "<init>":()V 7: ldc #6 // String AAA 9: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: invokestatic #9 // Method StaticString:()Ljava/lan g/String; 15: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: invokevirtual #8 // Method java/lang/StringBuilder. toString:()Ljava/lang/String; 21: areturn LineNumberTable: line 17: 0 public static java.lang.String getString4(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=0, args_size=0 0: new #4 // class java/lang/StringBuilder 3: dup 4: invokespecial #5 // Method java/lang/StringBuilder. "<init>":()V 7: ldc #6 // String AAA 9: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: invokestatic #9 // Method StaticString:()Ljava/lan g/String; 15: invokevirtual #7 // Method java/lang/StringBuilder. append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: invokevirtual #8 // Method java/lang/StringBuilder. toString:()Ljava/lang/String; 21: areturn LineNumberTable: line 20: 0 } C:\Users\hcd>
可以看出来getString3() 方法和getString4()方法的字节码指令一摸一样,也就是编译器帮我们做了优化。
由于String对象时不可变对象,因此在对字符串进行拼接时,String对象总是会生成新的对象,所以其性能相对较差。
StringBuilder:一个非线程安全的字符串缓冲类,jdk1.5后出现。
所以,编译器在字符串对象拼接时,自动帮我们用StringBuilder实现了字符串拼接。
相关推荐
Java字符串拼接是编程中常见的操作,特别是在处理大量数据或者构建复杂的输出时。然而,不同的字符串拼接方式在性能上存在显著差异。本篇文章将深入探讨Java中的字符串拼接技术,以及它们对程序效率的影响。 首先,...
总结来说,JDK 8对字符串拼接进行了优化,当字符串拼接在编译时可确定时,编译器会自动转换为使用`StringBuilder`。然而,对于运行时动态拼接的情况,开发者仍需手动使用`StringBuilder`或`StringBuffer`以获得最佳...
2. **字符串拼接**:在循环中使用`+`操作符进行字符串拼接会创建大量中间对象,效率低下。应优先考虑使用`StringBuilder`或`StringBuffer`(多线程环境)来累积字符串,它们提供了append方法,避免了不必要的内存开销...
2. **使用StringBuilder而非String拼接**:在循环中连接字符串时,StringBuilder比"+"操作符更高效。 3. **合理利用final关键字**:final可以提升方法内局部变量的访问速度,并有助于编译器进行优化。 4. **减少对象...
11. **使用StringBuffer代替String进行字符串拼接操作**,在多线程环境中,StringBuilder是线程不安全的,这时可以考虑使用StringBuffer。 以上只是Java优化的一部分内容,实际优化过程中还需要结合具体业务场景和...
2. **减少对象创建**:频繁的对象创建和销毁会增加垃圾回收的压力,可以考虑使用对象池、重用对象或者使用更轻量级的数据结构,如`StringBuilder`代替`String`进行字符串拼接。 3. **避免无谓的计算**:在循环中...
尽量减少嵌套循环,优化循环条件,使用StringBuilder而非+操作符进行字符串拼接。此外,使用预编译表达式(如PreparedStatement)代替动态SQL,可以提高数据库操作性能并防止SQL注入。 异常处理不应忽视。过度使用...
- 使用`StringBuilder`或`StringBuffer`代替`String`进行字符串拼接,尤其在循环中,前者提供了可变的特性,减少了对象生成。 - 使用`String.intern()`方法可以将字符串常量池中的引用返回,避免重复创建相同的...
在循环中拼接字符串时,`StringBuilder`和`StringBuffer`提供了更高效的追加操作,因为它们在内部维护了一个可变的字符数组,而字符串是不可变的,每次连接都会创建新的字符串对象。 2. 避免在循环内部创建对象。...
- **文本块(Text Blocks)**:这是一种新的字符串语法,用于表示多行文本,减少字符串拼接的繁琐和易错性。 - **ZGC(Z Garbage Collector)**:这是一个低延迟的垃圾收集器,适用于大内存应用,可以显著降低停顿...
4. **文本块(Text Blocks)**:Java 11引入了文本块,一种多行字符串的表示方式,减少了字符串拼接的繁琐,尤其在处理大量文本数据时更加方便。 5. **增强的switch表达式**:switch语句在Java 11中得到了增强,...
相比之下,`StringBuilder`或`StringBuffer`在拼接时不会生成新对象,因此更适合大量字符串操作。例如,避免使用`+`运算符连接字符串,而应该使用`StringBuilder.append()`方法。 ```java // 不推荐的方式 String ...
例如,使用StringBuilder而非String进行字符串拼接,可以显著减少内存分配和提高性能。 3. 数据库交互: 对于依赖数据库的应用,优化SQL查询和索引是关键。减少数据库连接的开销,缓存常用数据,以及合理设计...
1. **语言增强**:Java 7引入了一些重要的语法改进,如自动资源管理(try-with-resources)使得资源关闭更加便捷,多 catch 语句允许一个 try 块捕获多种类型的异常,以及字符串在常量池中的拼接优化等。 2. **类型...
比如,提倡使用参数绑定而非字符串拼接来构造SQL,避免全表扫描,合理设计数据库表结构和索引,以及正确使用事务隔离级别等。 六、工程规约 工程规约关注项目结构、依赖管理、持续集成等方面。手册推荐使用Maven或...
`BufferedReader`和`StringBuffer`是处理文件读取和字符串拼接的常见工具。`BufferedReader`可以从文件中逐行读取文本,而`StringBuffer`则用于在多线程环境中安全地拼接字符串。例如: ```java BufferedReader in ...
`CheckString`可能包含了一些字符串操作的实例,如检查字符串的空值、比较、拼接、查找子串等。 6. 所有的`.class`文件都是对应`.java`源代码文件编译后的结果,这意味着这个学习资料包含了从源代码到可执行代码的...
这个库的核心理念是将Java的强类型特性与HTML的生成过程相结合,避免了传统字符串拼接导致的错误和不易维护的问题。通过j2html,开发者可以更高效、更可靠地构建动态网页应用。 **类型安全的HTML生成** 在传统的...
这种特殊性提供了线程安全和性能优化,因为字符串常用于拼接操作,不可变性使得它们可以在多线程环境下共享而无需担心数据同步问题。此外,Java的JVM为了提高效率,引入了常量池的概念。常量池存储了程序中的字符串...