String字符串
concat方法拼接
String x="a";
String y="b";
x.concat(y)
concat源码中容易得出,concat方法通过创建一个长度为两字符串长度之和的byte数组来存放两字符串,然后将两个字符串依次放入数组中,实现了字符串的拼接。
至于为什么使用byte数组,上面讲过,String类型底层使用byte数组存储char数组,因此concat使用byte数组来存储字符串,如果用其他类型的数组就要进行类型转换。
注意:concat方法并不会对原对象进行改变,而是会返回一个新的String对象。不通过字符串常量池
通过加号拼接两个String对象
String z=x+y;
底层调用 new new StringBuilder().append(“a”).append(“b”).toString(),相当于new String(“ab”),不通过字符串常量池,因为z的值依赖于引用对象,它们随时可以改变,所以不能在编译时优化,只能通过StringBuilder创建
通过加号拼接两个字符串
String p="ab";
String x="a"+"b";
因为"a",“b"都是常量串,不可能发生变化了,所以javac在编译期间进行优化,结果在编译期确认为"ab”,此时字符串常量池StringTable已有"ab"串,x直接引用,所以p==x为True
String x="a";
String y="b";
String z=x+y;
String p="a"+"b";
sout(z==p)//结果为false
直接赋值
String a="b"
先去常量池拿到字符串,当做key去字符串池检索,如果StringTable没有,创建String对象,添加进去,如果有找到String对象地址,无论如何都返回String对象给a引用
intern方法 JDK1.8
public class Main {
public static void main(String[] args) {
//"a" "b" 被放入串池中,str则存在于堆内存之中
String str = new String("a") + new String("b");
//调用str的intern方法,这时串池中没有"ab",则会将该字符串对象放入到串池中,此时堆内存与串池中的"ab"是同一个对象
String st2 = str.intern();
//给str3赋值,因为此时串池中已有"ab",则直接将串池中的内容返回
String str3 = "ab";
//因为堆内存与串池中的"ab"是同一个对象,所以以下两条语句打印的都为true
System.out.println(str == st2);//true
System.out.println(str == str3);//true
}
}
调用字符串对象的intern方法,会将该字符串对象尝试放入到串池中
- 如果串池中没有该字符串对象,则放入成功,返回该字符串对象
- 如果有该字符串对象,则放入失败,返回常量池里的字符串对象
intern方法 JDK1.6
public class Main {
public static void main(String[] args) {
//此处创建字符串对象"ab",因为串池中还没有"ab",所以将其放入串池中
String str3 = "ab";
//"a" "b" 被放入串池中,str则存在于堆内存之中
String str = new String("a") + new String("b");
//此时因为在创建str3时,"ab"已存在与串池中,所以放入失败,但是会返回串池中的"ab"
String str2 = str.intern();
//false
System.out.println(str == str2);
//false
System.out.println(str == str3);
//true
System.out.println(str2 == str3);
}
}
调用字符串对象的intern方法,会将该字符串对象尝试放入到串池中
- 如果串池中没有该字符串对象,会将该字符串对象复制一份,再放入到串池中,此时串池中的该对象地址是复制的,与原字符串不是同一个对象
- 如果有该字符串对象,则放入失败,返回串池中字符串对象