一、String
1、String表示字符串类型,属于引用数据类型,不属于基本数据类型。
2、在java中随便使用双引号括起来的都是String对象。
3、java中规定,双引号括起来的字符串,是不可变的,也就是说"abc"自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"
4、在JDK当中双引号括起来的字符串,例如:“abc” "def"都是直接存储在“方法区”的“字符串常量池”当中的。
5、为什么把字符串存储在一个“字符串常量池”当中呢??
字符串的分配和其他的对象分配一样,需要耗费高昂的时间和空间为代价,如果需要大量频繁的创建字符串,会极大程度地影响程序的性能,因此 JVM 为了提高性能和减少内存开销引入了字符串常量池(Constant Pool Table)的概念。
6、字符串常量池的位置?
在JDK 7以前的版本中,字符串常量池是放在永久代中的。因为按照计划,JDK会在后续的版本中通过元空间来代替永久代,所以首先在JDK 7中,将字符串常量池先从永久代中移出,暂时放到了堆内存中。在JDK 8中,彻底移除了永久代,使用元空间替代了永久代,于是字符串常量池再次从堆内存移动到永久代中。
7、为什么将String设定为不可变的
因为String存储在方法区的字符串常量池里,一个字符串可能被多个对象引用,如果字符串可以修改会间接导致别的对象应用也别修改。
8、String的intern()方法?
当intern()方法被调用,如果字符串常量池中含有一个字符串和当前调用方法的字符串eqauls相等,那么就会返回池中的字符串。如果字符串常量池中没有的话,则首先将当前字符串加入到池中,然后返回引用。
9、为什么我们在使用HashMap的时候总是用String做key?
1)因为String是不可变的,String的hash值是在第一次计算出来后可以进行缓存,调用get()方法时就不用重复计算hash值,提高了效率。
2)String作为不可变对象,一旦创建就不可修改。这为HashMap的使用带来了一定的安全性。由于Key的不可变性,我们无法在HashMap中修改已存在的Key的值,这避免了在使用可变对象作为Key时可能引发的问题。同时,String类已经实现了equals()和hashCode()方法,确保了Key的比较和哈希计算的正确性。
10、字符串相加的原理?
String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = str1 + str2;
String str5 = "a" + "b";
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
问题:为什么str3和str4的地址不同?按理来说都是在字符串池中的对象
String str5 = “a” + “b”; 当字符串相加的部分中全部都是常量时,那么就会直接进入字符串池中进行操作,所以我们生成的str5对象地址就在字符串池中
String str4 = str1 + str2;当字符串相加部分中有变量,那么就会用StringBulider的方式来添加,那么返回的地址就是堆中StringBuilder对象的地址!
一个在堆中,一个在字符串池中,当然会是false。
二、StringBuffer,StringBuilder
1、什么是StringBuffer?
- StringBuffer 类是可变字符串类,创建 StringBuffer 类的对象后可以随意修改字符串的内容。
- 每个 StringBuffer 类的对象都能够存储指定容量的字符串,如果字符串的长度超过StringBuffer 类对象的容量,则该对象的容量会自动扩大。
- StringBuffer是被final修饰的类,不能被继承。
- StringBuffer的大部分方法都被synchronized方法修饰,所以多线程下操作StringBuffer是线程安全的。
2、 既然Java有了String类为什么还要实现StringBuffer类和StringBuilder类?
String是创建的字符串是不可变的,如果要修改就会产生新对象。而StringBuffer/StringBuilder创建的字符串则是可变字符串,修改时不会创建新对象,提高字符串操作效率。
3、StringBuilder和StringBuffer类的区别?
StringBuider和StringBufer最主要的区别就在于线程安全性上,Stingbuilder是一个非线程安全的类,也就是说,在多个线程同时访问或修改同一Stingbuilder对象时可能会出现数据错误混乱。而StringBuffer则是一个线程安全的类,不会出现上述问题。String类因为存储数据的value数组是被final修饰的,不存在线程安全问题,所以String也是线程安全的。