标签:end long another inf 抽象类 def row 增加 imp
##总结:
String:底层代码是一个用final修饰的char数组,是一个不可变的字符串,因此是线程安全的。对String字符串进行改变时,都会产生一个新的String对象,然后将指针指向String对象,影响系统性能,适用于少量字符串操作的情况。String初始化时,除了用构造函数进行初始化,还可以直接赋值(可以赋空值)。
StringBuilder:是可变字符串,支持并发操作,是线程安全的,效率低;适用于多线程下在字符串缓冲区进行大量操作的情况。StringBuilder只能用构造函数的形式来初始化(不可以赋空值)。
StringBuffer修改字符串的原理:首先创建一个stringbuffer对象,然后调用append方法,最后调用toString方法。使用stringbuffer类时,每次都是对stringbuffer对象本身进行操作,不会生成新对象并改变对象的引用。
StringBuilder:是可变字符序列,不支持并发操作,是线程不安全的,效率高;适用于单线程下在字符缓冲区进行大量操作的情况。StringBuilder只能用构造函数进行初始化(不可以赋空值)。
三者的运行速度:StringBuilder>StringBuffer>String
String为字符串常量,而StringBuffer和StringBuilder均为字符串变量,即String对象一旦创建,该对象就是不可更改的,但后两者的对象是变量,是可以更改的。
Java中对象String对象进行的操作,实际上是一个不断创建新对象并且将旧对象回收的过程,所以执行速度很慢。在单线程下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全,而StringBuffer每次都需要判断锁,效率相对较低。
StringBuilder和StringBuffer都继承于AbstractStringBuilder类,实现了Serializable序列化接口、Appendable接口及CharSequence接口。
一、String
1.string的底层代码为一个用final修饰的char数组,这就意味着定义一个string变量后,该变量的内容是不可变的。
1 public final class String
2 implements java.io.Serializable, Comparable<String>, CharSequence {
3 private final char value[]; //String其实就是用char[]实现的。
4 private int hash; // Default to 0 //缓存字符串的hash Code,默认值为 0
5 //String类的内部就是维护了一个char数组
6 private static final long serialVersionUID = -6849794470754667710L;
7 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
因为string实现了Serializable接口,所以支持序列化(把对象转换为字节序列的过程)和反序列化(把字节序列恢复为对象的过程)。Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
2.构造方法
使用字符数组、字符串构造一个string
使用字节数组构造一个string
使用StringBuffer和StringBuilder构造一个string
1 public String(char value[]) {
2 this.value = Arrays.copyOf(value, value.length);
3 }
4 public String(char value[], int offset, int count) {
5 if (offset < 0) {
6 throw new StringIndexOutOfBoundsException(offset);
7 }
8 if (count < 0) {
9 throw new StringIndexOutOfBoundsException(count);
10 }
11 if (offset > value.length - count) {
12 throw new StringIndexOutOfBoundsException(offset + count);
13 }
14 this.value = Arrays.copyOfRange(value, offset, offset+count);
15 }
这两个构造方法都用到了Arrays工具类的copyOf方法,在这两个方法里面都调用了System.arraycopy方法;因为System.arraycopy是一个系统本地方法,所以这个方法的效率很高,所以在构造string时效率也很高。
3.compareTo方法(因为string实现了Comparable接口,所以必须实现compareTo方法)
1 public int compareTo(String anotherString) {
2 int len1 = value.length;
3 int len2 = anotherString.value.length;
4 int lim = Math.min(len1, len2);
5 char v1[] = value;
6 char v2[] = anotherString.value;
7 int k = 0;
8 while (k < lim) {
9 char c1 = v1[k];
10 char c2 = v2[k];
11 if (c1 != c2) {
12 return c1 - c2;
13 }
14 k++;
15 }
16 return len1 - len2;
17 }
4.length,charAt方法
1 public int length() {
2 return value.length;
3 }
4 public boolean isEmpty() {
5 return value.length == 0;
6 }
7 public char charAt(int index) {
8 if ((index < 0) || (index >= value.length)) {
9 throw new StringIndexOutOfBoundsException(index);
10 }
11 return value[index];
12 }
5.getBytes方法
调用了StringCoding.encode方法,encode方法调用另外一个重载的方法。
1 static byte[] encode(char[] ca, int off, int len) {
2 String csn = Charset.defaultCharset().name();
3 try {
4 return encode(csn, ca, off, len);
5 } catch (UnsupportedEncodingException x) {
6 warnUnsupportedCharset(csn);
7 }
8 try {
9 return encode("ISO-8859-1", ca, off, len);
10 } catch (UnsupportedEncodingException x) {
11 MessageUtils.err("ISO-8859-1 charset not available: "+ x.toString());
12 System.exit(1);
13 return null;
14 }
15 }
二、StringBuffer
1.StringBuffer继承于AbstracctStringBuilder抽象类,实现了Serializable接口和CharSequence接口。
1 public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
2 static final long serialVersionUID = 3388685877147921107L;
3 public StringBuffer() {
4 super(16);
5 }
2.StringBuffer初始化及扩容机制
1)StringBuffer()的初始容量为16,当该对象的实体存放的字符长度大于16时,实体容量就会自动增加。StringBuffer对象可以通过length()方法获取实体中存放的字符序列长度,通过capacity()方法来获取当前实体的实际容量。
2)StringBuffer(int size)可以指定分配给该对象的实体的初始容量参数为参数size指定的字符个数。当该对象的实体存放的字符长度大于size个字符时,实体的容量就会自动增加,以便存放所增加的字符。
3)StringBuffer(String s)指定给对象的实体的初始容量为参数字符串s的长度额外再加16个字符。当该对象的实体存放的字符序列长度大于size个字符时,实体的容量自动增加。
1 public StringBuffer(String str) {
2 //这个执行父类的带参构造函数AbstractStringBuilder(int capacity)
3 super(str.length() + 16);
4 append(str);
5 }
6 //append 是用 synchronized 修饰的,所以是线程安全的
7 public synchronized StringBuffer append(String str) {
8 //执行父类的append(str)
9 super.append(str);
10 return this;
11 } //父类 AbstractStringBuilder 的 append 方法
扩容算法:使用append方法在字符串后面追加内容时,如果长度超过了子符串存储空间大小就需要进行扩容:创建新的存储空间更大的字符串,将旧的复制过去;再进行字符串append添加时,会先计算添加后字符串的大小,传入一个方法:ensureCapacityInternal这个方法进行是否扩容的判断,需要扩容就调用expandCapacity方法进行扩容,尝试将新容量扩大为原来大小的2倍+2,if判断一下,容量如果还不够,直接扩充到需要的容量大小。
添加字符串过程:
-->先检查内部char[]数组是否需要扩容;
-->如果需要扩容则进行扩容,然后将原来的元数据copy到新数组中;
-->再将新添加的元数据加入到新数组中。
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 *元数组char[]的扩容过程
14 */
15 void expandCapacity(int minimumCapacity) {
16 int newCapacity = value.length * 2 + 2;
17 if (newCapacity - minimumCapacity < 0)
18 newCapacity = minimumCapacity;
19 if (newCapacity < 0) {
20 if (minimumCapacity < 0) // overflow
21 throw new OutOfMemoryError();
22 newCapacity = Integer.MAX_VALUE;
23 }
24 value = Arrays.copyOf(value, newCapacity);
25 }
26 /**
27 *扩容实现
28 */
29 public static char[] copyOf(char[] original, int newLength) {
30 char[] copy = new char[newLength];
31 System.arraycopy(original, 0, copy, 0,
32 Math.min(original.length, newLength));
33 return copy;
34 }
35 if (str == null)
36 return appendNull();
37 int len = str.length();
38 //检查char[]数组是否需要扩容,扩容,并将原来的数据copy进去新扩容的数组中
39 ensureCapacityInternal(count + len);
40 //将新添加的数据添加到StringBuilder中的char[]数组中,实现字符串的添加
41 str.getChars(0, len, value, count);
42 count += len;
43 return this;
44 }
三、StringBuilder
String、StringBuffer、StringBuilder的区别
标签:end long another inf 抽象类 def row 增加 imp
原文地址:https://www.cnblogs.com/HuiH/p/11729560.html