String、StringBuffer和StringBuilder的区别和实现原理
https://www.cnblogs.com/shangxiaofei/p/6377136.html
String
String是java中用的最频繁的类之一,其内部原理是通过char[]数组实现的。其实内部char[]是定义的常量 .
private final char value[];
public String() {
this.value = "".value;
}//默认是"";
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
一旦定义之后不可改变,能够改变的String变量的引用地址。比如String b=new String ();指向String 创建的在堆中的对象地址,b= new String("ssss");这样b再次指向另一个在堆中的某一对象地址。而之前堆中的String对象的value是常量并没有发生改变
简而言之创建的String变量可以重新指向对象但是String的一个对象中的value数组是不能改变的这也就是为什么定义的对象无法进行末尾追加值的原因(因为你想要改变String的长度需要操作value对象而value对象呗关键字final修饰了)。
注意
1 当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
2 Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
3 使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
4 使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。
另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。
StringBuilder
StringBuffer类是线程安全的,他的方法都是synchronized关键字修饰的
StringBuilder类是线程不安全的
StringBuilder是可变长度的字符串长度类但是不是线程安全的而Stringbuffer 是线程安全的这是他们两者的区别(线程安全速度就慢),(详见看线程安全详解)StringBuilder也是用char[]构成的但是他可以改变对象的长度。因为内部并没有使用final关键字,在StringBuilder的append方法中对对象value值进行修改。
线程安全性
这三个类在进行操作时的速度关系为:StringBuilder > StringBuffer > String
由于String中进行操作时都会新建一个char[ ]数组代替原来的char[ ]数组,所以速度最慢
StringBuffer线程安全,每个方法都有synchronized同步阻塞,所以操作速度受影响
StringBuilder没有同步阻塞的限制,所以操作速度最快
使用场景
-
如果要操作少量的数据用 = String
-
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
-
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
常用方法、
String都比较熟悉,这里只整理StirngBuffer/StringBuilder类的方法,这两个类大多数方法都是继承于AbstractStringBuilder父类
1、append(String str) 追加内容到当前StirngBuffer/StringBuilder对象的末尾,类似于字符串的连接
2、deleteCharAt(int k)删除指定位置的字符,然后将剩余的内容形成新的字符串
3、delete(int start, int end) 删除指定区间以内的所有字符,包含start,不包含end索引的区间
4、insert(int index, String str) 在StirngBuffer/StringBuilder对象指定位置中插入内容str,然后形成新的字符串
5、reverse() 将StirngBuffer/StringBuilde对象中的内容反转,然后形成新的字符串
==与equals的区别
==指的是指向对象的地址是否相同。equal内部方法是把char[]的每一个值进行对比相同就返回true有一个不同就返回false。
例子:
String s1=new String("s");
String s2=new String("s");
System.out.println(s1==s2);
System.out.printlc(s1.equals(s2));
最后运行结果为false true;因为new出来对象地址不同所以不相同,而值是一样的故而得到的是false和true
String s1="s";
String s2="s";
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
最后运行结果为true true这是
因为它们都是从缓冲池取出来的,由于string类比较特殊,jdk专门做了缓存优化。
Java运行时会维护一个String Pool(String池)。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。
也就是说需要看string创建的方式:
参考博客
https://blog.csdn.net/Orient_/article/details/89343115