String s="a"+"b"+"c"到底创建了几个对象?

常量折叠技术:在编译期间,编译器会将编译器常的加减乘除运算过程在编译过程中折叠。编译器通过语法分析,将常量表达式计算求值,并用求出来的值替换表达式,而不必等到运行期间再进行运算处理,从而在运行期间节省处理器资源。

  • 下面来对比三种不同写法,观察那些情况下会发生常量折叠

我们对比反编译后的字节码文件以及使用jclasslib bytecode viewer查看字节码信息

  1. 我们来分析一下语句,查看反编译后的字节码文件,进行了常量折叠
1
String s = "a" + "b" + "c";

字节码信息如下:

直接对比是否指向同一个对象:

1
2
3
String s = "a" + "b" + "c";
String t = "abc";
System.out.println(s == t);

结果:

  1. 再来对比,没有进行常量折叠
1
2
String s1 = "ab";
String s = s1 + "c";

字节码信息如下:

是否指向常量池中的常量:

1
2
3
4
String s1 = "ab";
String s = s1 + "c";
String t = "abc";
System.out.println(s == t);

结果:

  1. 在观察如下语句,与2唯一的区别就是给s1添加了final修饰,可以发现又发生了常量折叠
1
2
final String s1 = "ab";
String s = s1 + "c";

字节码信息如下:

是否指向同一个对象:

1
2
3
4
final String s1 = "ab";
String s = s1 + "c";
String t = "abc";
System.out.println(s == t);

结果:

发生常量折叠必须是编译器常量:

  • 被声明为final
  • 基本数据类型或者字符串类型
  • 声明时就已经初始化了
  • 使用常量表达式进行初始化