JAVA回顾巩固之String、StringBuilder、StringBuffer结合源码比较
2016-07-24 10:21
676 查看
今天回顾巩固了一下java的基础知识,那么String、StringBuilder、StringBuffer之间有什么区别呢?
尝试查看源码之后,有了一个清晰的认识。
首先大体说明,通常情况下大家都知道,String是不可变的字符串对象,StringBuilder、StringBuffer是可变的,其中StringBuilder线程不安全,StringBuffer线程安全,具体情况如下:
String:
源码注释写到:“Strings are constant; their values cannot be changed after they are created.“
具体到代码中:
看一看到,String其实就是一个char数组,但是由于使用了private修饰,且没有给出外部接口,又使用了final修饰,使得这个String对象一旦创建,就不能进行修改。
至于为什么可以对String进行赋值等操作,是因为对String进行赋值等操作以后,其实是给了String变量一个新的String对象,而之前被创建的对象依然存在于内存中。
StringBuilder和StringBuffer:
从源码中可以看出StringBuilder和StringBuffer都继承于AbstractStringBuilder,实现的接口也是一致的。
再来看AbstractStringBuilder:
其中最重要的一个方法就是append,同个这个方法,使得他们可以对数组进行扩容,我们都知道数组一旦被定义,那么长度就是一定的,不能再进行改变了,那他们是怎么做到对数组进行扩容的呢,于是查看了AbstractStringBuilder中以下源码:
这里可以发现,其实并不是对原本的数组进行了修改,而是新建了一个数组,将原数组内容进行了copyOf操作,让value引用了新数组,旧的数组等待被回收。
而后通过观察发现,他们实现的方法也基本一致。
StringBuilder:
这里可以看出唯一的区别是StringBuffer的方法基本上都有synchronized修饰,synchronized本意是同步的,java中用它来修饰一个方法或一块代码时,能保证同一时刻最多只有一个线程能执行改代码。所以有synchronized修饰即线程安全的。
比较的同时,通读了3个类中的源代码,发现了很多方法是以前不曾注意过的,但是都很有用。
尝试查看源码之后,有了一个清晰的认识。
首先大体说明,通常情况下大家都知道,String是不可变的字符串对象,StringBuilder、StringBuffer是可变的,其中StringBuilder线程不安全,StringBuffer线程安全,具体情况如下:
String:
源码注释写到:“Strings are constant; their values cannot be changed after they are created.“
具体到代码中:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[];<pre name="code" class="java"> <span style="font-family: Arial, Helvetica, sans-serif;">…</span><span style="font-family: Arial, Helvetica, sans-serif;">…</span><pre name="code" class="java">}
看一看到,String其实就是一个char数组,但是由于使用了private修饰,且没有给出外部接口,又使用了final修饰,使得这个String对象一旦创建,就不能进行修改。
至于为什么可以对String进行赋值等操作,是因为对String进行赋值等操作以后,其实是给了String变量一个新的String对象,而之前被创建的对象依然存在于内存中。
StringBuilder和StringBuffer:
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
从源码中可以看出StringBuilder和StringBuffer都继承于AbstractStringBuilder,实现的接口也是一致的。
再来看AbstractStringBuilder:
abstract class AbstractStringBuilder implements Appendable, CharSequence { /** * The value is used for character storage. */ char[] value; /** * The count is the number of characters used. */ int count;接口AbstractStringBuilder中,可以看到,StringBuilder和StringBuffer其实也是char数组,只不过没有用private和final进行修饰,这意味着他们是可变的。
其中最重要的一个方法就是append,同个这个方法,使得他们可以对数组进行扩容,我们都知道数组一旦被定义,那么长度就是一定的,不能再进行改变了,那他们是怎么做到对数组进行扩容的呢,于是查看了AbstractStringBuilder中以下源码:
void expandCapacity(int minimumCapacity) { int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; if (newCapacity < 0) { if (minimumCapacity < 0) // overflow throw new OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } value = Arrays.copyOf(value, newCapacity); }
public static char[] copyOf(char[] original, int newLength) { char[] copy = new char[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
这里可以发现,其实并不是对原本的数组进行了修改,而是新建了一个数组,将原数组内容进行了copyOf操作,让value引用了新数组,旧的数组等待被回收。
而后通过观察发现,他们实现的方法也基本一致。
StringBuilder:
private StringBuilder append(StringBuilder sb) { if (sb == null) return append("null"); int len = sb.length(); int newcount = count + len; if (newcount > value.length) expandCapacity(newcount); sb.getChars(0, len, value, count); count = newcount; return this; }
public StringBuilder append(StringBuffer sb) { super.append(sb); return this; }StringBuffer:
public synchronized StringBuffer append(StringBuffer sb) { super.append(sb); return this; }
这里可以看出唯一的区别是StringBuffer的方法基本上都有synchronized修饰,synchronized本意是同步的,java中用它来修饰一个方法或一块代码时,能保证同一时刻最多只有一个线程能执行改代码。所以有synchronized修饰即线程安全的。
比较的同时,通读了3个类中的源代码,发现了很多方法是以前不曾注意过的,但是都很有用。
相关文章推荐
- POJ 2264 Advanced Fruits DP+记录路径
- JS中的==运算: [''] == false ―>true
- [LEETCODE]52. N-Queens II
- 省市二级联动小案例讲解
- LeetCode[357] Count Numbers with Unique Digits
- LeetCode "Wiggle Subsequence" !
- [JAVA]String StringBuffer StringBuilder
- 安卓6.0版本更新以后无法利用BluetoothDevice.ACTION_FOUND查找周围设备
- UITableView 到达顶部或底部的判断
- String、StringBuffer、StringBuilder
- JS中的==运算: [''] == false ―>true
- 为Mac OS X 中的MAMP安装 libmosquitto PHP扩展
- UITextFiled、UITextView按字节限制输入长度
- UISearchBar
- UEditor学习笔记(一)
- 【Leetcode】Guess Number Higher or Lower II
- JBuilder中切换编辑文件标签的键盘快捷键
- junit4定义测试集TestSuite Declaration
- JBuilder中光标错位的解决办法
- QQLite 插件开发 之 html解析 CsQuery(C#)