閱讀java源碼的一些體會
一军掂、CharSequence接口
public interface CharSequence {
int length();
char charAt(int index);
CharSequence subSequence(int start, int end);
public String toString();
public default IntStream chars() {……}
public default IntStream codePoints() {……}
}
? ?default是java8的新特性,具體可以想見文檔昨悼,顯然此接口主要是保證有獲取內(nèi)容的公共接口蝗锥。還實現(xiàn)了轉(zhuǎn)換為IntStream的默認函數(shù)。
二率触、String類的一些感覺
1.結(jié)構(gòu)
- 請看類的實現(xiàn):
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence{
private fianl char value[];
private int hash;
private static final long serialVersionUID = -6849794470754667710L;
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
/**省略實現(xiàn)細節(jié)
**/
}
? ?可以看到此時的結(jié)構(gòu)體一共有四個變量终议。扣除為了實現(xiàn)進程間傳遞的變量葱蝗。主要的變量就是存儲內(nèi)容value和hash穴张。其中value為其取值,而hash則是String的hash函數(shù)值两曼。
? ?這里可以看到String類型中的value變量是final類型的皂甘,是不可變的變量,同時String類型也沒有提供修改char[]數(shù)組的接口悼凑。這就可以肯定value在構(gòu)造之初之后就不能改變叮贩。這表示新的內(nèi)容產(chǎn)生新的對象。
2.常用代碼分析
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
if (srcBegin < 0) {
throw new StringIndexOutOfBoundsException(srcBegin);
}
if (srcEnd > value.length) {
throw new StringIndexOutOfBoundsException(srcEnd);
}
if (srcBegin > srcEnd) {
throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
}
//將內(nèi)容從value中復(fù)制到dst數(shù)組中佛析,arraycopy是native方法,這個方法顯
//然可以有相當(dāng)強大的效率
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
//產(chǎn)生了新的對象哦
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}
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--;
}
//還是產(chǎn)生了新對象哦
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}
? ?此外,replace彪蓬、splite都和Pattern和matcher有關(guān)寸莫,將數(shù)組內(nèi)容替換,并返回新的對象档冬。
二膘茎、StringBuilder
1.結(jié)構(gòu)
- 請看類的實現(xiàn):
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence{
/** use serialVersionUID for interoperability */
static final long serialVersionUID = 4383685877147921099L;
…………
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
}
? ?這里可以看到并沒有其他的變量,那么我們看其父類:
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;
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
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;
}
…………
}
? ?其中這里有一段關(guān)于vlaue數(shù)組長度擴展的關(guān)鍵代碼:
/**
* This implements the expansion semantics of ensureCapacity with no
* size check or synchronization.
*/
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);
}
? ?綜上所述酷誓,我們可以看到披坏,StringBuilder直接調(diào)用AbstractStringBuilder的父接口,其append每次首先檢查char[]數(shù)組長度盐数,如果大小不夠棒拂,就重新擴充大小,并拷貝原來的數(shù)組內(nèi)容玫氢,可以說StringBuilder是緩存的String帚屉,因此效率更高。想reaplace漾峡、delete這些方法都是在緩存數(shù)組上操作攻旦,然后返回對象本身。但如果需要獲得String類型生逸,則還是會返回String類型的對象牢屋。
三且预、StringBuffer
1.結(jié)構(gòu)
- 請看類的實現(xiàn)(通過我的read,方法都有synchronized烙无,是線程安全得):
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
* 關(guān)鍵字代表此變量之存在于內(nèi)存中锋谐,而不能傳輸(例如持久化)
*/
private transient char[] toStringCache;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
static final long serialVersionUID = 3388685877147921107L;
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
…………
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) {
expandCapacity(minimumCapacity);
}
}
}
2.關(guān)鍵代碼
/**
* @throws IndexOutOfBoundsException {@inheritDoc}
* @see #length()
*/
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
}
@Override
public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null;
value[index] = ch;
}
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
@Override
public synchronized StringBuffer insert(int index, char[] str, int offset,
int len)
{
toStringCache = null;
super.insert(index, str, offset, len);
return this;
}
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
? ?可以說StringBuffer是線程安全得,但是其他的核心代碼幾乎是StringBuilder的拷貝皱炉。顯然StringBuilder效率上要更好怀估,然而多線程下顯然是有危險的。
四合搅、總結(jié)
? ? StringBuffer和StringBuilder異同:
- StringBuffer是線程安全得可變序列多搀,而StringBuilder是5.0新增的一個特性,用于和StringBuffer做兼容灾部,其不保證線程安全康铭,可以看到StringBuilder顯然要比StringBuffer快。
- 為了保證快速的toString赌髓,StringBuffer提供了字符緩存數(shù)組从藤,顯然這時候非常快锁蠕。
- String類每次改變都將產(chǎn)生新對象夷野。因而StringBuffer一般情況下要比String快。
- System.arraycopy是native方法荣倾,顯然拷貝效率要更好悯搔,如果需要拷貝,可以 優(yōu)先考慮使用arraycopy拷貝普通數(shù)組舌仍。
- default關(guān)鍵字主要用于擴展接口的同時避免修改集成樹妒貌,可以提供接口的默認實現(xiàn),transient保證變量在持久化的過程中智能待在內(nèi)存铸豁。