面试官 :为什么String设计成不可变的?
小小白 :主要是为了确保String对象中存储的值不会被改变,充分利用字符串常量池的优化策略,同时字符串对象的hashCode也不会被改变。如果String设计成可变的,那么自定义的类就可以通过集成String,重写其中的方法将其存储的值改变。如果String是可变的,将String类型变量作为参数传递的过程中,存储的将有可能会被改变,这样会导致安全隐患。
面试官 :平时编码过程中字符串的拼接使用什么?
小小白 :如果不会出现多线程并发的情况,使用StringBuilder;如果会出现多线程并发的情况,使用StringBuffer。
面试官 :为什么不使用加号(+)?
小小白 :StringBuffer就不对比说了,它比StringBuilder多了线程安全控制,同样的方法使用synchronized控制并发访问,性能上必定会比StringBuilder差。举一个使用样例就能看出差别,下面的代码执行就会发现,使用StringBuilder会比加号的方式快很多(忽略输出中的字符串拼接方式)。
// 加号方式拼接字符串
long startTimeInMillis = Calendar.getInstance().getTimeInMillis();
String result = "start:";
for(int i = 0; i < 10000; i++){
result = result + i;
}
long endTimeInMillis = Calendar.getInstance().getTimeInMillis();
long executeTimeInMillis = endTimeInMillis - startTimeInMillis;
System.out.println("executeTimeInMillis:" + executeTimeInMillis);
输出结果:executeTimeInMillis:342
// StringBuilder#append方法拼接字符串
long startTimeInMillis = Calendar.getInstance().getTimeInMillis();
StringBuilder result = new StringBuilder("start:");
for (int i = 0; i < 10; i++) {
result.append(i);
}
long endTimeInMillis = Calendar.getInstance().getTimeInMillis();
long executeTimeInMillis = endTimeInMillis - startTimeInMillis;
System.out.println("executeTimeInMillis:" + executeTimeInMillis);
输出结果:executeTimeInMillis:18
面试官 :JDK不是已经对字符串使用加号的拼接做优化了吗,为什么还是会慢?
小小白 :使用JDK8编译使用加号方式拼接字符串的代码,然后使用javap -c命令反编译class文件,结果如下:
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: invokestatic #2 // Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
3: invokevirtual #3 // Method java/util/Calendar.getTimeInMillis:()J
6: lstore_1
7: ldc #4 // String start:
9: astore_3
10: iconst_0
11: istore 4
13: iload 4
15: sipush 10000
18: if_icmpge 47
21: new #5 // class java/lang/StringBuilder
24: dup
25: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
28: aload_3
29: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
32: iload 4
34: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
37: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
40: astore_3
41: iinc 4, 1
44: goto 13
47: invokestatic #2 // Method java/util/Calendar.getInstance:()Ljava/util/Calendar;
50: invokevirtual #3 // Method java/util/Calendar.getTimeInMillis:()J
53: lstore 4
55: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
58: new #5 // class java/lang/StringBuilder
61: dup
62: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
65: ldc #11 // String executeTimeInMillis:
67: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
70: lload 4
72: lload_1
73: lsub
74: invokevirtual #12 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
77: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
80: invokevirtual #13 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
83: return
从上面的21可以看到,在这一行new了一个StringBuilder对象,然后开始执行对象的初始化和字符串的拼接append方法,注意看44,这里执行了goto 13,就是转到13继续执行,从13开始会发现,后面还是new了一个StringBuilder对象,然后执行对象的初始化和字符串的拼接append方法,接着继续goto 13,也就是说循环体中不断的创建StringBuilder对象,调用append方法实现字符串的拼接。虽然,JDK编译的时候使用StringBuilder优化了原来通过不断创建新String对象的拼接字符串的方式,但是在循环体中不断创建对象的方式不是最优的,而且这样频繁创建对象会可能会触发GC。所以,显然直接使用StringBuilder#append方法会高效一些。
面试官 :那是不是都不能使用加号(+)的方式拼接字符串?
小小白 :也不是的。如果是简单的静态字符串拼接(拼接中不需要动态的计算字符串值),可以使用加号的方式,因为编译器在编译阶段会聪明的计算出结果。
面试官 :下面代码的运行结果又是什么?
String t0 = new String("hello") + new String("world");
t0.intern();
String t1 = "helloworld";
System.out.println(t0 == t1);
小小白 :JDK1.7之前的版本为false,JDK1.7开始为true。
面试官 :为什么结果不同?
请点击阅读 《String引发的提问,我差点跪了》
推荐阅读 :
面试官一步一步的套路你,为什么SimpleDateFormat不是线程安全的
都说ThreadLocal被面试官问烂了,可为什么面试官还是喜欢继续问
点点" 在看 "
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learn Python 3 the Hard Way
Zed A. Shaw / Addison / 2017-7-7 / USD 30.74
You Will Learn Python 3! Zed Shaw has perfected the world’s best system for learning Python 3. Follow it and you will succeed—just like the millions of beginners Zed has taught to date! You bring t......一起来看看 《Learn Python 3 the Hard Way》 这本书的介绍吧!
RGB HSV 转换
RGB HSV 互转工具
HEX CMYK 转换工具
HEX CMYK 互转工具