String源碼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 /** * Initializes a newly created {@code String} object so that it represents * an empty character sequence. Note that use of this constructor is * unnecessary since Strings are immutable. */ public String() { this.value = "".value; } ... public String substring(int beginIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } int subLen = value.length - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); } 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); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } public CharSequence subSequence(int beginIndex, int endIndex) { return this.substring(beginIndex, endIndex); } public String concat(String str) { int otherLen = str.length(); if (otherLen == 0) { return this; } int len = value.length; char buf[] = Arrays.copyOf(value, len + otherLen); str.getChars(buf, len); return new String(buf, true); } public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this; }
分析源碼:
1.String 類爲 final 修飾,說明該類不能被重寫。 2.String類型的字符串實際上是以 字符的形式存儲的,(private final char value[]) 3.任何操做字符串的方法都是創建在新的字符串之上的,字符串的操做不會影響到原來的字符串對象,而是新建一個字符串副本以供操做。安全
String s1 = "daxiong"; String s2 = "daxiong"; String s3 = new String("daxiong"); String s4 = new String("daxiong");多線程
JVM 內存機制中針對不一樣的屬性進行不一樣的分區存儲。字面量以及符號都會存在於方法區的常量池中,這裏以HotSpot虛擬機爲例,那麼 String s1 = "daxiong"; 其中 "daxiong" 字面量就會存儲到方法區的常量池中,當執行到 Stirng s2 = "daixong";的時候虛擬機會到方法區的常量池中進行檢測,若是檢測到常量池中存在"daxiong",那麼就不會再次建立,若是沒有檢測到,則會從新建立,這裏很顯然已經存在,則不會再次建立新的"daxiong"。而對於String s3 = new String("daxiong");JVM專門分配一塊內存區域叫作堆來存儲對象實例,也就是經過new關鍵字建立的對象(注意:隨着技術的發展,當前的虛擬機不是全部的經過new關鍵字建立的實例都會放到堆中),那麼s3這個實例對象就會在堆上被分配內存空間,固然String s4 = new String("daixong");也一樣會在堆上被分配內存空間。而這二者的引用都會存儲到棧空間,棧空間又分爲JVM虛擬機棧和本地方法棧兩類,上面的實例的引用都在JVM虛擬機棧中存儲。因此綜上所述:s1 == s2,s1 != s3/s4,s3 != s4;app
String s = "hello"; for(int i = 0;i < 1000;i++){ s += "world"; }
上面這段代碼是經過String直接操做的,那麼根據以前分析的String的特性可知:每執行一步 "+" 操做,須要先建立一個新的對象,而後將原對象賦值給新對象,而後在新對象上進行 "+"操做,而後再將新對象返回。以此類推...,執行完上面的代碼須要建立 1000 個新對象,很浪費空間。ui
StringBuilder sb = new StringBuilder("hello"); for(int i = 0;i < 1000;i++){ sb.append("world"); }
上面這段代碼只會建立一個對象,即StingBuilder,它的操做字符串效果是在原對象上進行的,不會浪費太多空間。this
經過查看源碼發現StringBuilder 和 StringBuffer的成員變量和方法大體相同,只不過StringBuffer 在方法上加入了同步關鍵字:synchronized,也就是說StringBuffer提供了多線程訪問線程安全策略,是線程安全的。那麼從這裏可知:線程
StringBuilder 執行效率快,線程不安全;StringBuffer執行慢,線程安全。code