没使用加号拼接字符串,面试官竟然问我为什么

栏目: IT技术 · 发布时间: 6年前

面试官 :为什么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被面试官问烂了,可为什么面试官还是喜欢继续问

Java注解是如何玩转的,面试官和我聊了半个小时

如何去除代码中的多次if而引发的一连串面试问题

String引发的提问,我差点跪了

就写了一行代码,被问了这么多问题

面试官:JVM对锁进行了优化,都优化了啥?

synchronized连环问

三分钟快速搞定git常规使用

没使用加号拼接字符串,面试官竟然问我为什么

点点" 在看 "   


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Learn Python 3 the Hard Way

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 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具