由一道面试题开始:
/*
这段代码去掉final之后结果完全不一样
*/
public class TestMode {
public static void main(String[] args) {
final String a = "1";
final String b = "2";
String c = a + b;
String d = "12";
System.out.println(c == d);//返回true,证明a,b的确作为编译期常量
//加入了常量池,而c也在编译期确定其值
}
}
在有
final
的情况下是这样的:
这个不多说
去掉
final
之后:
这里做了什么呢?
内部是创建了一个StringBuilder
对象,然后不停地append
追加
最后调用StringBuilder
对象的toString
方法得到一个String
对象
注意这个toString
方法会new
一个String
对象
所以接下来研究一下 StringBuilder
:
package CodeTest;
public class StringTimeTest {
public static void test1() {
String str1 = "abc";
String str2 = "de";
String str = str1 + str2;
}
public static void test2() {
String str = "abc" + "de";
}
public static void test3() {
StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");
}
public static void main(String[] args) {
long startTime1=System.nanoTime(); // 获取开始时间
test1();
long endTime1=System.nanoTime(); // 获取结束时间
System.out.println("test1运行时间: "+(endTime1-startTime1)+"ns");// 输出程序运行时间
long startTime2=System.nanoTime(); // 获取开始时间
test2();
long endTime2=System.nanoTime(); // 获取结束时间
System.out.println("test2运行时间: "+(endTime2-startTime2)+"ns");// 输出程序运行时间
long startTime3=System.nanoTime(); // 获取开始时间
test3();
long endTime3=System.nanoTime(); // 获取结束时间
System.out.println("test3运行时间: "+(endTime3-startTime3)+"ns");// 输出程序运行时间
}
}
运行结果如下:
这里不能一起执行,以免常量池造成的混淆
可以看到,test1
和test3
的结果是差不多的
随后加了 final
再看看:
test1
就和 test2
差不多了。
8说了。