String面试题
总结的很好:https://blog.csdn.net/qq_45950109/article/details/116992408
String特点
1.被final关键字修饰,不能被继承。实现Serializable,表示支持序列化。实现Comparable,表示可以排序。
2.底层是char数组和hash,jdk9将char数组改成byte数组节省空间
3.两种创建方式
//字面量的定义方式,这种方式会把"a"字符串存放在堆内存中的字符串常量池里面
String s1="a";
//创建对象的方式,首先在堆中创建一个对象,然后将"a"放在字符串常量池中,s2指向的是堆中"a"引用地址
String s2=new String("a");
System.out.println((s1 == s2)); // false
4.一旦创建不能修改,字符串常量池中不会有重复的字符串
a
b
c
字符串拼接操作
1.字符串常量拼接
//编译器在编译时将“+”号两端的字符串解析为常量 helloworld!
String s = "hello" + "world!";
// 反编译后
String s0 = "helloworld!";
System.out.println((s0 == s1)); // true
2.字符串变量拼接
字符串拼接的时候,只要其中有一个字符串是变量,结果就在存放在字符串常量池外的堆中。
/**
* 编译期确定
* 对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。
* 所以此时的"a" + s1和"a" + "b"效果是一样的。故结果为true。
*/
String s0 = "ab";
final String s1 = "b";
String s2 = "a" + s1;
System.out.println((s0 == s2)); // true
如果字符串拼接出现啦变量就会用StringBuilder的append方法拼接,最后掉toString方法会new一个新对象。
如果拼接的结果调用intern()方法,则主动将常量池中还没有的字符串对象放入池中,并返回此对象地址
new String()到底创建了几个对象
创建了3个对象
//编译器在编译时将“+”号两端的字符串解析为常量 helloworld!
String s = "hello" + "world!";
//对象1:"hello" + "world!"
//对象2:"world!"
//对象3:"helloworld!"
创建了两个对象
创建了6个对象
intern()方法的使用
String s1 = new String(“abc”).intern():
1.如果字符串常量池存在"abc",s1返回的地址是常量池中"abc"的引用地址
2.如果字符串常量池不存在在"abc",在堆内存中创建一个对象,然后在字符串常量池中存入"abc"对象的引用地址,此时字符串变量池中存的就是堆内存"abc"的引用地址。
情况1
情况2
对于程序中大量存在的字符串,尤其其中存在很多重复字符串时,使用intern()方法可以节省内存空间,也即是在创建字符串的时候后面跟上intern方法,即new String(“abc”).intern()
大的网站平台,需要内存中存储大量的字符串。比如社交网站,很多人都存储:北京市,海淀区等信息。这时候如果字符串都调用intern()方法,就会明显降低内存的大小。