对于String的深入解析
原创
©著作权归作者所有:来自51CTO博客作者959_1x的原创作品,请联系作者获取转载授权,否则将追究法律责任
String
不可变特性
创好了就不可以改变,如果添加啥东西的或者改变的话必须重写造。
原因:StringTable底层为map的key,不会存储相同内容的字符串的
jdk6的时候StringTable容量为1009
jdk7的时候容量为60013,最小为无限制
jdk8的时候为60013,最小1009
jdk6的时候StringTable放在永久代中
jdk7的时候放在堆中
jdk8的时候放在堆中
为什么改变位置?
1.因为permisize默认比较小,不敢放
2.永久代垃圾回收比较低,堆的垃圾回收频率高,容易报出OOM错误
public void test1(){
String s1 = "atguigu";
String s2 = "atguigu";
// s2 = "Zjy";
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
}
结果为
原因很明显,String为引入数据类型,所以==比较的是地址值
public void test1(){
String s1 = "atguigu";
String s2 = "atguigu";
s2 = "Zjy";
System.out.println(s1 == s2);
System.out.println(s1);
System.out.println(s2);
}
结果为
这里就体现了String的不可变特性
当赋给另外一个值的时候会生成一个新的String然后指向
public void test2(){
String s1 = "atguigu";
String s2 = "atguigu";
s2 += "Zjy";
System.out.println(s1);
System.out.println(s2);
}
不可变性的再度体现
public void test3(){
String s1 = "abc";
String s2 = s1.replace('a', 'm');
System.out.println(s1);
System.out.println(s2);
}
不可变性的再度体现
String的拼接操作
- 常量与常量的拼接的结果在常量池中,原理为编译优化
- 常量池中不会出现相同的常量
- 只要其中有一个是变量的话,就会保存在堆中,变量拼接的原理为StringBuilder
- 如果调用的是inner方法,则主动将常量池中没有的字符串对象放入池中,返回该对象的地址,有的话返回存在的地址
public void test1(){
String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);
}
public void test2(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
String s8 = s6.intern();
System.out.println(s3 == s8);//true
}
因为是字符串拼接。所以s3保存在常量池中,而设计到有变量的s4-s7保存在堆中,而堆中的对象就不一样了。所以第一个是true,后6个都是false,最后一个inner方法是检查字符串常量池中有无,如果有的话返回的是那个对象的地址,所以s3 == s8