前言:1.String|StringBuffer|StringBuilder 三者底层实现都是char[]+相关操作。
2.String对象后面跟这一个+号,而再后面的对象不是String,编译器会试着将this转换成一个String(通过调用this上的toString()方法)
3.当字符串链接(+|+=)时,如果有未知的链接数据,那么jvm都会创建一个StringBuilder对象来生成此次的String对象。
1、String 类:1.字符串都是对象
2.一旦初始化就不可以被更改(内部是private final char[])存储,所有String对象是不可变的.
3.通过String类的构造函数,可以将数组(byte,char,int)转换成字符串。
功能: 1.获取 2.判断 3.转换 4.切割 5.替换 6.比较 7.去除空格
2、StringBuffer:线程安全类(底层char[]数组来存储)
1.是一个字符串缓冲区,其实就是一个容器。
2.长度是可变的,任意类型都行(是将任意数据都转成字符串进行存储)
3.容器对象提供很多对容器中数据操作功能(添加,删除,查找,修改)
4.最后拼接成一个字符串(toString())
StringBuffer和StringBuilder的区别?
StringBuffer:线程同步,多线程访问安全。
StringBuilder:非同步的,单线程访问效率高。
3、字符串比较
规则:1.在编译时期,可以确定下来的字符串,进行比较(==),相同?返回true,反之false
2.当字符串链接(+|+=)时,如果有未知的链接数据,那么jvm都会创建一个StringBuilder对象来生成此次的String对象。
3.当有s1.intern()方法参与时,规制如下:
a.常量池中如果没有此字符串,会直接将s1的地址存储在常量池内
b.常量池中如果已经有此字符串,那么此处引用返回的就是常量池中的地址
例如:String s1 = "lucky";//编译时期可以确定下来
String s2 = "luc"+"ky"; //jvm直接是常量池中取,无其他操作
s1==s2//true
//查看jvm字节码发现,编译器自动创建了一个StringBuilder对象,用以构造最终的String,并为每个字符串调用一次append()方法,最后toString()生成结果
"lu" append到StringBuilder中
"ck" append到StringBuilder中
"y" append到StringBuilder中
最终StringBuilder的toString()生成一个String对象
String s3 = "lu"+"ck"+String.valueOf("y");//编译时期无法确定下来
s1==s3//false
String s4 = new String("lucky");//编译时期无法确定下来
s1==s4//false
例如:// 此时生成了4个对象 常量池中的"word" + 2个堆中的new--"word"对象 + s1指向的堆中的对象(此时常量池不会生成"wordword")
String s1 = new String("word")+ new String("word");//wordword
String s2 = "wordword";
System.out.println(s1 == s2); // false
//----------------------------------------------------
String s1 = new String("word")+ new String("word");
String s3 = new String("word")+ new String("word");
s1.intern();// 常量池中没有"wordword",会直接将s1的地址存储在常量池内
String s2 = "wordword";// 此处用的是常量池中的地址
System.out.println(s1 == s2);// true
System.out.println(s2 == s3);// false
//----------------------------------------------------
String s1 = new String("word")+ new String("word");
String s3 = new String("word")+ new String("word");
String s2 = "wordword";// 常量池中生成"wordword"
String s4 = s1.intern();// 常量池中有"wordword"常量,会直接使用常量池中的
String s5 = s3.intern();// 常量池中有"wordword"常量,会直接使用常量池中的
System.out.println(s1 == s2);// false
System.out.println(s1 == s4);// false
System.out.println(s3 == s2);// false
System.out.println(s2 == s3);// false
System.out.println(s2 == s4);// true
System.out.println(s2 == s5);// true
//----------------------------------------------------
// 常量池中生成"Hello"
String s3 = "Hello";
// 此时堆中只生成了一个对象,常量池中的"Hello"常量已经有了
String s4 = new String("Hello");
4、编译器行为
1)String对象后面跟这一个+号,而再后面的对象不是String,编译器会试着将this转换成一个String(通过调用this上的toString()方法)
例如:本类中重写toString()
public String toString(){
return "lucky-->"+this;//此处会产生递归。
}
5、Formatter类(格式,类型转换)(--->String.format())
在java中,所有新的格式化功能都是由java.util.Formatter类处理
例如:formatter.format("%s The Turtle is at (%d,%f)",name,x,y);
//结果:lisi The Turtle is at (3,4.0)
%f 字符串类型
%d int
%f float|double
...
6、注意事项
1.同步synchronized代码块都不使用String作为锁对象.
2.