String,StringBuffer和StringBuilder
Posted perferect
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了String,StringBuffer和StringBuilder相关的知识,希望对你有一定的参考价值。
java 基础中字符串用到最多的就是String,StringBuffer和StringBuilder,这三个也是面试中最常问到的,三者之间的异同,其实实际工作中,我们大致知道使用场景,但是要用理论话的语言去总结,总是比较麻烦。
1.String
1.1继承实现关系
1.2 源码分析
1> final 修饰的类无法被继承;
public final class String implements java.io.Serializable, Comparable<String>, CharSequence
2> String的数据存放在final修饰的char数组中,所以String对象初始化之后值不能改
/** The value is used for character storage. */ private final char value[];
3>String 值比较,总共两种方式,一种是继承了Comparable接口,实现compareTo()方法通过逐个字符串比较;
另一种方法是,compareToIgnoreCase() 方法,通过静态成员类,实现Comparator方法,逐个char变大写比较,变小写比较;
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable { //。。。。。。 if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { // No overflow because of numeric promotion return c1 - c2; } } } //。。。。。 }
4>字符串之间的关联,String提供了静态的方法,可以将多个字符串通过delimiter进行拼接;
public static String join(CharSequence delimiter, CharSequence... elements) {
}
5>字符串的trim()方法,对字符串双端去空
public String trim() { int len = value.length; int st = 0; char[] val = value; /* avoid getfield opcode */ while ((st < len) && (val[st] <= ‘ ‘)) { st++; } while ((st < len) && (val[len - 1] <= ‘ ‘)) { len--; } return ((st > 0) || (len < value.length)) ? substring(st, len) : this; }
2.AbstractStringBuilder
2.1 继承实现关系
2.2源码分析
1>初始长度设置,通过构造方法:数据存储在非fianl的char数组中,通过构造函数传参初始化;
AbstractStringBuilder(int capacity) { value = new char[capacity]; }
2>.在append的时候,char[]数组进行扩容,一般是现有值长度的2倍+2
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len);//已有长度+拼接字符串长度 为最小的容量 str.getChars(0, len, value, count); count += len; return this; } private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) {//最小长度大于现有长度时,进行扩容 value = Arrays.copyOf(value, newCapacity(minimumCapacity));//复制生成新的char[]数组 } } private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2;//容量编程 现有长度的2倍+2 if (newCapacity - minCapacity < 0) { //扩容后还是小于最小长度时,将最小长度赋值给扩容长度 newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity; }
3.StringBuilder
1.源码分析
1> final修饰的类,不可以继承
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
2> 默认初始长度为16
public StringBuilder() { super(16); }
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
3>转成字符串toString()方法是生成新的String对象
@Override public String toString() { // Create a copy, don‘t share the array return new String(value, 0, count); }
4.StringBuffer
1.源码分析
1> final修饰不可继承
public final class StringBuffer
2> toString缓存数据;
1.通过一个transient修饰的字段toStringCache,进行转字符串存储;
2.在每个值改变的操作将toStringCache设置为空;
3.在toString()方法中,如果toStringCache为空,就copy新的char[]数组赋值给toStringCache ;
4.如果StringBuffer中的数值没变动,调用toString方法的时候,直接调用toStringCache就可以了;
private transient char[] toStringCache; @Override public synchronized StringBuffer append(long lng) { toStringCache = null; super.append(lng); return this; } @Override public synchronized String toString() { if (toStringCache == null) { toStringCache = Arrays.copyOfRange(value, 0, count); } return new String(toStringCache, true); }
通过上面的可以知道,如下:
相同点:
1.都是final类,不可以继承;
2.内部存取数据的都是char数组;
3.都实现了CharSequeue,可以对字符串进行相关操作;
不同点:
1.String 和StringBuilder,StringBuffer的区别:
- 1. String的值final 数组,赋值后不可改变;StringBuilder,StringBuffer 非final char数组,初始化后可以改变值;
- 2. String的字符拼接,每拼接一次,相当于生成一个新的字符串;StringBuilder,StringBuffer通过给内部的char数组扩容,不用生成新的对象,效率更高;
2.StringBuilder 和 StringBuffer 之间的区别:
- 1. StringBuffer的所有操作都加synchorinized
- 2. StringBuffer的toString方法,有缓存,多次toString效率更高;
- 3.StringBuilder 效率更高,但是线程不安全;
常见问题:
1.自己写一个String,或StringBuilder类可以替换原有的JDK的String么?
答:这个问题其实和String,StringBuilder没关系了,而涉及到的是JVM类加载中,双亲委派模型;
双亲委派模型,是类加载器接收到当前类的加载请求,并不会直接去加载,而是逐级向父加载器发送请求,当父加载器没有相关的类,当前子加载器才自行加载;
以上是关于String,StringBuffer和StringBuilder的主要内容,如果未能解决你的问题,请参考以下文章
(转)String,StringBuffer与StringBuilder的区别
Java常用类--String类(StringBuilder 和 StringBuffer)介绍
Java String, StringBuilder, StringBuffer