1 String和StringBuilder、StringBuffer的区别
请看:这篇博客
2 StringBuilder保证线程安全的原因
请看:这篇博客
3 synchronized和lock锁区别与原理
请看:这篇博客
4 判断String s1 = “abc”;String s2 = “abc”;s1==s2是否等于true
String类代表字符串,字符串是常量,常量需要进入到内存中的方法区的常量池
进入常量池规则:如果常量池中没有这个常量,就创建一个,如果有就不再创建了
所以大概的步骤如下:
- 所以s1首先会在常量池中创建“abc”对象,“abc”对象是有地址值的,“abc”对象将地址值赋给s1。
- 当s2的时候,此时常量池中已经存在了“abc对象”,所以就不需要再创建了,
- s2的引用也指向了常量池中的“abc”对象,两个引用指向了同一个对象,s1和s2地址值一样,所以==号比较的时候返回true;
5 String s = new String(“abc”);在内存中创建了几个对象?
2个对象或1个对象
分析:
- s首先会在
常量池创建“abc”字符串常量
,如果之前存在的话,就不会新创建 - 当
new
的时候就会在堆内存中创建一个对象
, - 此时会把常量池中的字符串常量拷贝一份副本到给到堆内存中的对象,堆内存中的这个对象就会把地址值赋给s。
常量池中对象
的地址值和堆内存中对象
的地址值是不一样
的,s指向的是堆内存中的对象
,不是常量池中的对象。- 此时堆内存中有一个对象,常量池中有一个对象,所以创建了2个对象。
6 String s1 = new String(“abc”);String s2 = “abc”;判断s1==s2是否相等?
不相等;
分析:
- 由5可知,new的指向的是堆里面的地址;
- 所以当执行完s1的时候,内存中会有两个对象,一个在堆内存,一个在常量池,且地址值是不一样的,
s1指向的是堆内存中的对象
,而当执行到s2的时候,s2指向的是常量池中的对象
,地址值不一样,- 所以==号判断的时候返回false。
- s1和s2的属性值是一样的,所以equals方法比较时返回true
7 String s1 = “a”+“b”+“c”;String s2 = “abc”;判断s1==s2
true
分析:
- Java中有常量优化机制,“a”、“b”、“c”本身就是字符串常量,所以在编译时,“a”+“b”+"c"就是“abc”字符串;
- 所以就在常量池中创建了“abc”字符串
- 指向到s2时,就是从常量池中取,所以==返回true
8 String s1 = “a”;String s2 = “abc”;String s3 = s1+“bc”;判断s3==s2
false
分析:
- s1+"c"中s1不是常量,不能用常量优化机制来分析
- s1和s2会分别在常量池中创建"ab"、"abc"两个对象
- s3的时候是字符串串联,
s3
的时候会在对内存中创建StringBuilder(或者StringBuffer)对象
,通过append方法拼接成“abc”对象
,此时的“abc”是StringBuilder(或者StringBuffer)类型的,通过调用toString方法转成String对象
,此时s3指向的是堆内存中这个String对象
s2指向的是常量池中的对象,s3指向的是堆内存中的对象,所以==号比较返回false