在開發過程當中String是一個高頻使用的類,可是一直沒有仔細去閱讀過源碼。打開源碼得知String是一個final的類,它實現了Serializable、Comparable和CharSequence接口java
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 //省略... }
String類包含三個屬性:數組
/** 存儲字符串中的字符*/ private final char value[]; /** 緩存string的hashcode值 */ private int hash; // Default to 0 /** * 序列持久化 */ private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
String的底層使用char數組實現的。String重寫了Object的equals和hashcode的方法。緩存
String的equals方法實現以下:jvm
/** * 比較當前字符串和指定的對象,只有當指定對象不爲null而且對象中的字符序列相同時 * 才返回true */ public boolean equals(Object anObject) { //兩個對象的引用地址相同返回true if (this == anObject) { return true; } //只有String類型的數據纔有效 if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; //若是包含的字符長度不相等返回false if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; //從後往前判斷單個字符,同等序號若是不相等則返回false while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
String的hashCode實現以下:測試
String是使用value值來做爲hash運算,那麼若是String的value相等那麼它們的hashCode值一定相等,那麼用String的equals比較也是相等的,同時也能夠看出對於String若是它的equals相等,那麼它的hashCode值優化
也必定相等,固然hashCode值相等不能表明兩個String相等。this
在String的Hash計算中使用一個計算常數31,31是通過測試均勻分佈的獲得的結果,並且31能夠被jvm優化採用移位運算31 = (i<<5)-1code
/** * 返回字符串的hash值 * 計算公式: * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * s[i]是指String中的字符,n是指String的長度 */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
String intern方法介紹:intern方法是一個native的方法,當intern方法被調用,它會使用equals方法去字符串常量池中比較查找,若是找到則返回,若是沒有找到的將新的字符串添加到字符串常量池中,而後返回對象的引用。對於任何的兩個String對象s和t,當前僅當s.equals(t)爲true時,s.intern()==t.intern()才爲true對象
public native String intern();
String的內存操做:接口
在jvm內存分配中有兩個重要的部分,一個是heap一個是stack,棧用於存儲對象的引用,
heap用戶存儲具體的對象。在jdk1.7後(字符串常量池被移到了heap中)jvm分配 一些內存專門用於存儲string的字面量,這是堆內存的一部分,它被稱做字符串常量池(String Constant Pool),例如 :String a = "abc"; 若是使用了new操做來建立字符串則對象會被存儲到堆內存中
注意:當你使用一個字面量來建立一個String對象時,jvm會首先在字符串常量池中檢查是否已經存在,若是找到則返回對象的引用,若是沒有的建立一個新的對象