Java笔记之浅析String以及Stringbuffer

来源:互联网 发布:网页生成软件 编辑:程序博客网 时间:2024/06/05 03:56

String十分常用,一般用到字符串时都会先想到String,但是String有那么好用吗!String与StringBuffer有什么区别,为什么更推荐使用Stringbuffer。

带着问题来探索
首先看源码中String类与StringBuffer

对比他们的构造函数可以发现一些区别

String

    private final char value[];    public String(String original) {        this.value = original.value;        this.hash = original.hash;    }     //虽然等同但是并不==但是他们的哈希值确实一样且equal比较相等     //直接赋值会去常量池中比较     String str = "abc";     //等同于    char data[] = {'a', 'b', 'c'};    //new对象是在堆中    String str = new String(data);

StringBuffer

   public StringBuffer(String str) {       //super是指AbstractStringBuilder        super(str.length() + 16);        append(str);    }

由于String的许多方法继承自抽象类AbstractStringBuilder为了一探究竟附上源码

    char[] value;    AbstractStringBuilder(int capacity) {        value = new char[capacity];    }

对比上述不难发现String与StringBuffer最大的区别在于String是不可以改变的
因为储存String的字符数组是final类型的
而StringBuffer是可以改变的,其储存数组是非final类型的

还有一点就是 String是实现了常量池技术的类之一,
所谓常量池就是当出现字符字面量直接赋值给String时进入常量池中寻找
该字符串若有则直接返回该字符串的引用否则将该字符串加入进去。这样做的目的为了减少重复相同的字符串字面量的创建。
但是常量池是有限的且一旦创建除非程序退出否则几乎不会被回收。Java的回收算法主要集中在堆区。虽然StringBuffer创建的重复字符串会在堆区占用多个空间
但是StringBuffer可以被回收。当你创建大量不同的字符串时你的程序可能会由于常量池满了而挂掉。这也是十分危险的,也是推荐使用StringBuffer的原因之一。
可以参考常量池

如果String这么差为什么还一直在用。其实String并没有那么差,String方法众多且十分高效。并且常量池溢出是比较极端的情况。
String 的 replaceAll 以及 split 支持正则表达式 非常好
而且StringBuffer可转换为String
所以当遇到需要对字符串进行操作时可以将StringBuffer转化成String

StringBuffer另一个优点是线程安全

StringBuffer对字符串的操作都是同步的。而String类是非线程安全的

那么StringBuffer是如何对字符进行操作的呢

下面是StringBuffer的append方法

    //同步的  线程安全    @Override    public synchronized StringBuffer append(String str) {        toStringCache = null;        super.append(str);        return this;    }

AbstractStringBuilder 的append方法

    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;    }    //检查是否添加String后会超出字符数组的范围    private void ensureCapacityInternal(int minimumCapacity) {        // overflow-conscious code        if (minimumCapacity - value.length > 0)            expandCapacity(minimumCapacity);    }    //解决添加String后会超出字符数组的范围    void expandCapacity(int minimumCapacity) {        //扩大两倍        int newCapacity = value.length * 2 + 2;        //扩大两倍后小于添加String后的数组大小        if (newCapacity - minimumCapacity < 0)            //新数组大小等于添加String后的数组大小            newCapacity = minimumCapacity;            //内存满了        if (newCapacity < 0) {            if (minimumCapacity < 0) // overflow                throw new OutOfMemoryError();            newCapacity = Integer.MAX_VALUE;        }        //将旧数据复制到新数组        value = Arrays.copyOf(value, newCapacity);    } 

通过append方法来对StringBuffer的整体实现有个框图,其实StringBuffer的实现确实比较简单,其比String优势也就是 线程安全,可以修改。

String与StringBuffer的优劣比较

String类操作String的方法比较全而StringBuffer没有几个。
StringBuffer可以修改字符串而String不行
String类实现了常量池技术StringBuffer没有
StringBuffer和String使用的区别不大,其实都是字符数组只不过StringBuffer的可以修改
StringBuffer是线程安全的而String不是
String类型可以直接接受字符串字面量StringBuffer的New对象
StringBuffer某种程度上说浪费内存空间。而String得提防常量池溢出
StringBuffer与String可以相互转化。所以StringBuffer可以优先使用

总结
并没有对StringBuffer和String的用法作过多的介绍,因为他们的用法十分简单。
而对他们的优劣进行比较。写这篇文章的目的是了解String以及StringBuffer的优缺点。从而合理的使用他们

水平有限 若有错误 欢迎指正

1 0