【1】String,StringBuffer,StringBuillder的底层结构研究

简介: 一:StringBuffer的底层(1)线程安全的字符串操作类(2)通过synchronized关键字声明同步方法,保证多线程环境下数据安全1 @Override2 public synchronized StringBuffer append(String str) {3 toStringCache = null;4 super.append(str);5 return this;6 }View Code(3)底层存储数据的Char[]数组,初始化时,该数组的长度是16。

一:StringBuffer的底层

(1)线程安全的字符串操作类

(2)通过synchronized关键字声明同步方法,保证多线程环境下数据安全

1 @Override
2     public synchronized StringBuffer append(String str) {
3         toStringCache = null;
4         super.append(str);
5         return this;
6     }
View Code

(3)底层存储数据的Char[]数组,初始化时,该数组的长度是16。如果构造函数有新传入字符转str,则16基础上加str.length.

 1 /**
 2 *无参构造
 3 */
 4 public StringBuffer() {
 5         super(16);
 6 }
 7 
 8 
 9 
10 /**
11 *带参构造
12 */ 
13 public StringBuffer(String str) {
14         super(str.length() + 16);
15         append(str);
16     }
17 
18 /**
19 *初始化char[]数组
20 */
21    AbstractStringBuilder(int capacity) {
22         value = new char[capacity];
23     }
View Code

 (4)添加字符串的过程

-->先检查内部char[]数组是否需要扩容

-->如需要扩容则进行扩容,然后将原来元数据copy到新数组中。

-->再将新添加的元数据加入到新char[]数组中

 1 public AbstractStringBuilder append(String str) {
 2         if (str == null)
 3             return appendNull();
 4         int len = str.length();
 5         //检查char[]数组是否需要扩容,扩容,并将原来的数据copy进去新扩容的数组中
 6         ensureCapacityInternal(count + len);
 7         //将新添加的数据添加到StringBuilder中的char[]数组中,实现字符串的添加
 8         str.getChars(0, len, value, count);
 9         count += len;
10         return this;
11     }
12 
13 
14 /**
15 *元数组char[]的扩容过程
16 */
17     void expandCapacity(int minimumCapacity) {
18         int newCapacity = value.length * 2 + 2;
19         if (newCapacity - minimumCapacity < 0)
20             newCapacity = minimumCapacity;
21         if (newCapacity < 0) {
22             if (minimumCapacity < 0) // overflow
23                 throw new OutOfMemoryError();
24             newCapacity = Integer.MAX_VALUE;
25         }
26         value = Arrays.copyOf(value, newCapacity);
27     }
28 
29 
30 /**
31 *扩容实现
32 */
33    public static char[] copyOf(char[] original, int newLength) {
34         char[] copy = new char[newLength];
35         System.arraycopy(original, 0, copy, 0,
36                          Math.min(original.length, newLength));
37         return copy;
38     }
View Code

 

 

二:StringBuillder的底层

 (1)线程非安全的字符串操作类

 (2)字符串的添加没有加同步处理,涉及到数组扩容,容易产生脏数据,破坏数据正确性

 (3)底层结构和StringBuffer实现基本一样,只是没有做同步处理。

--->StringBuffer和StringBuillder都继承抽象类AbstractStringBuilder,该抽象类实现了字符串操作的方法。

--->StringBuffer和StringBuillder的实现,运用了模板方法的设计模式,将核心数据操作放在父类方法里,子类实现自己的独有特色的功能,涉及核心操作,调用父类方法。

 

三:String的底层

 

String类没有提供用于修改字符串的方法。String类对象为不可变字符串,如字符串string=”HELLO”永远只包含HELLO这几个字母,而不能修改其中任何一个字符。当然可以修改字符串变量string的引用,让它引用另一个字符串。
不可变字符串有一个优点:编译器可以让字符串实现共享。实际上只有字符串常量(使用“ ”声明,存储在字符串常量池中)是共享的,subStrng,+等操作产生的结果不能共享。
比较字符串值是否相等时使用equals()方法,不能使用==,==比较的是字符串的地址是否相同。如果字符串在常量池中,可以使用==比较,因为指向的都是同一个字符串。

直接使用 ” ” 声明的String对象会直接存储在常量池中,(可以实现共享)
1.String str1=”first”;
jvm在运行时先查找常量池中是否有该字符串,如果有则直接返回该字符串的引用给first(实现了字符串 的共享) ;否则先在常量
池中创建该字符串并返回引用。
此时只会在常量池中创建String对象,不会在堆中创建。
2.String str2=new String(“second”);
该代码生成了两个String对象。因为使用了“”会现在常量池中查找是否存在second对象,没有则创建
否则不创建;在常量池创建完成后,由于使用了new,jvm会在堆中创建内容相同的String对象,并将引用
返回给str2.
3.String str3=”what”; String str4=str3+”a nice day”;
运行时,+ 相当于new,所以堆中会有“what a nice day”对象;常量池中会有”what” “a nice day”两个对象,而不会有”what a nice day”对象。

4.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

5.测试类

 1 package com.yeepay.sxf.mianshi.pagkage;
 2 
 3 public class StringBufferAndStringBuillder {
 4 
 5     public static void main(String[] args) {
 6 //        String a="abc";
 7 //        String b=new String(a);
 8 //        //【true】a和b比较的是内容。便利各自的char[]数组进行比较
 9 //        System.out.println("a和b比较==>"+a.equals(b));
10 //        //【false】 a和b比较的是地址。a在常量池中  b在堆内存中
11 //        System.out.println("a和b比较==>"+a==b);
12         
13         test02();
14         
15     }
16     
17     
18     public static void test01(){
19         /**
20          * 你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:
21             String str = “This is only a” + “ simple” + “test”;
22             
23             其实就是:
24             String str = “This is only a simple test”;
25             
26             所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:
27             
28              String str2 = “This is only a”;
29 
30     String str3 = “ simple”;
31 
32     String str4 = “ test”;
33 
34     String str1 = str2 +str3 + str4;
35 
36     这时候JVM会规规矩矩的按照原来的方式去做。
37          */
38     }
39     
40     
41     public static void test02(){
42          //string3指向常量池中的字符串second
43          //string4指向堆中的字符串second
44          //所以值相同,引用不同
45          String string3="second";
46          String string4=new String("second");
47          System.out.println(string3==string4);
48         System.out.println(string3.equals(string4));
49 
50          //string5指向常量池中的字符串third
51          //string6一开始指向堆中的字符串third,但是调用intern()方法之后,且该方法调用时先检查常量池中是否有值为string6
52          //的字符串,如果有则返回该字符串的引用,否则在常量池中创建该字符串,并返回引用
53          //所以一开始引用不相等,后来相等
54          String string5="third";
55          String string6=new String("third");
56          System.out.println(string5==string6);
57          string6=string6.intern();
58          System.out.println(string5==string6);
59     }
60 }
View Code

 

相关文章
|
3月前
|
存储 安全 Java
【JAVA基础】String、StringBuilder和StringBuffer的区别——巨详细
String是不可变的,StringBuilder和StringBuffer是可变的。而StringBuffer是线程安全的,而StringBuilder是非线程安全的。
|
2月前
|
存储 XML 缓存
Java字符串内幕:String、StringBuffer和StringBuilder的奥秘
Java字符串内幕:String、StringBuffer和StringBuilder的奥秘
24 0
|
6月前
|
算法 Java 数据库
抽象类和接口 && String的理解 && StringBuilder和StringBuffer && 异常的基本用法 && 时间复杂度
抽象类和接口 && String的理解 && StringBuilder和StringBuffer && 异常的基本用法 && 时间复杂度
40 0
|
4月前
|
安全 Java 调度
Java基础面试,String,StringBuffer,StringBuilder区别以及使用场景
* String是final修饰的,不可变,每次操作都会产生新的对象。 * StringBuffer和StringBuilder都是在原对象上进行操作 * StringBuffer是线程安全的,StringBuilder是线程不安全的。 * StringBuffer方法是被synchronized修饰的
|
7天前
|
移动开发 安全 Java
String、StringBuffer 、StringBuilder、StringJoiner
String、StringBuffer 、StringBuilder、StringJoiner
|
1月前
|
存储 安全 Java
String、StringBuilder、StringBuffer的区别
String、StringBuilder、StringBuffer的区别
13 0
|
1月前
|
安全 Java
针对String、StringBuffer、Stringbuilder区别及使用场景
针对String、StringBuffer、Stringbuilder区别及使用场景
|
1月前
|
安全 Java API
String和StringBuffer的区别
String和StringBuffer的区别
|
1月前
|
安全 Java API
Java String类(3):StringBulider和StringBuffer详解
Java String类(3):StringBulider和StringBuffer详解
|
1月前
|
存储 安全 Java
36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法
36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法
29 0