String为什么是不可变的?
String 类中使用final关键字修饰字符数组保存字符串,private final char[] value,所以String对象是不可变的。
String、StringBuffer和StringBuilder的区别是什么?
可变性
String类中使用final关键字修饰字符数组来保存字符串,private final char value[],所以String对象是不可变的。而StringBuilder与StringBuffer都继承自AbstractStringBuilder类,AbstractStringBuilder
也使用字符数组保存字符串char[] value,但是没有用final关键字修饰,所以这两种对象都是可变的。
线程安全性
StringBuffer对方加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方进行加同步锁,所以是非线程安全的。
性能
每次对String类进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer每次都会对对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%~15%左右的性能提升,但却要冒多线程不完全的风险。
对于三者使用的总结
操作少量的数据:适用String
单线程操作字符串缓冲区下操作大量数据:使用StringBuilder
多线程操作字符串缓冲区下操作大量数据:适用StringBuffer
String s1 = new String("abc");这句话创建了几个字符串对象?
会创建1或者2个字符串对象
如果字符串常量池中不存在字符串对象”abc“的引用,那么会在堆中创建2个字符串对象”abc“。
示例代码(JDK1.8):
![](https://i-blog.csdnimg.cn/blog_migrate/38be3b3fe76798c899a8f1157970a4fb.png)
对应的字节码:
![](https://i-blog.csdnimg.cn/blog_migrate/865f597ef60fb278d13495d14e22dd05.png)
lbc命令用于判断字符串常量池中是否保存了对应的字符串对象的引用,如果保存了的话直接返回,如果没有保存的话,会在堆中创建对应的字符串对象并将该字符串的引用保存到字符串常量池中。
如果字符串常量池中已存在字符串对象”abc“的引用,则只会在堆中创建一个字符串对象”abc“。
示例代码(JDK1.8):
![](https://i-blog.csdnimg.cn/blog_migrate/fbebc601120ec7a0ac5e391680a1136c.png)
对应的字节码:
![](https://i-blog.csdnimg.cn/blog_migrate/e9fbfe2c136ef81e60f9f97007067f06.png)
7这个位置的ldc命令不会在堆中创建新的字符串对象”abc“,这是因为0这个位置已经执行了一次ldc命令,已经在堆中创建过一次字符串对象”abc“了。7这个位置执行ldc命令会直接返回字符串常量池中字符串对象”abc“对应的引用。
请写出下列代码的运行结果
Stringa=“bfrt”;
String b= new String(“bfrt”);
String c="bf"+"rt”;
System.out.printin(a==b);
System.out.printin(b==c);
System.out.printin(a=c);
如何将字符串反转?写一段demo代码
// ⽅法⼀: 把str转化成字符数组
public static void demo1(String str){
char[] chars = str.toCharArray();
for (int i = 0,j = chars.length - 1; i < j;i++,j--){
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
System.out.println(new String(chars));
}
// ⽅法⼆: 使⽤StringBuffer的反转⽅法reverse()
public static void demo2(String str){
StringBuffer sb = new StringBuffer(str);
StringBuffer sb1 = sb.reverse();
System.out.println(sb1.toString());
}
intern方法有什么作用?
String.intern()是一个native(本地)方法,其作用是将指定的字符串对象的引用保存在字符串常量池中,可以简单分为两种情况:
如果字符串常量池保存了对应的字符串对象的引用,就直接返回该引用。
如果字符串常量池中没有了保存对应的字符串对象的引用,那就在常量池中创建一个指向该字符串的引用并返回。
示例代码(JDK1.8):
// 在堆中创建字符串对象”Java“
// 将字符串对象”Java“的引⽤保存在字符串常量池中
String s1 = "Java";
// 直接返回字符串常量池中字符串对象”Java“对应的引⽤
String s2 = s1.intern();
// 会在堆中在单独创建⼀个字符串对象
String s3 = new String("Java");
// 直接返回字符串常量池中字符串对象”Java“对应的引⽤
String s4 = s3.intern();
// s1 和 s2 指向的是堆中的同⼀个对象
System.out.println(s1 == s2); // true
// s3 和 s4 指向的是堆中不同的对象
System.out.println(s3 == s4); // false
// s1 和 s4 指向的是堆中的同⼀个对象
System.out.println(s1 == s4); //true