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的深入解析_常量池
原因很明显,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的深入解析_常量池_02
这里就体现了String的不可变特性
当赋给另外一个值的时候会生成一个新的String然后指向


    public void test2(){
String s1 = "atguigu";
String s2 = "atguigu";
s2 += "Zjy";
System.out.println(s1);
System.out.println(s2);
}

对于String的深入解析_hadoop_03

不可变性的再度体现


    public void test3(){
String s1 = "abc";
String s2 = s1.replace('a', 'm');
System.out.println(s1);
System.out.println(s2);
}

对于String的深入解析_java_04
不可变性的再度体现

String的拼接操作
  • 常量与常量的拼接的结果在常量池中,原理为编译优化
  • 常量池中不会出现相同的常量
  • 只要其中有一个是变量的话,就会保存在堆中,变量拼接的原理为StringBuilder
  • 如果调用的是inner方法,则主动将常量池中没有的字符串对象放入池中,返回该对象的地址,有的话返回存在的地址
    public void test1(){
String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);
}

对于String的深入解析_java_05

    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
}

对于String的深入解析_hadoop_06

因为是字符串拼接。所以s3保存在常量池中,而设计到有变量的s4-s7保存在堆中,而堆中的对象就不一样了。所以第一个是true,后6个都是false,最后一个inner方法是检查字符串常量池中有无,如果有的话返回的是那个对象的地址,所以s3 == s8