類繼承關(guān)系中圖
特點
String
來看幾個例子
String s1 = "hello world";
String s2 = "hello world";
System.out.println(s1 == s2);
輸出結(jié)果是true
String s1 = new String("hello world");
String s2 = new String("hello world");
String s3 = "hello world";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
輸出結(jié)果是 false沪羔、true巍沙、true
在 Java 編譯好的 class 文件中葵姥,有個區(qū)域被稱為常量池(Constant Pool),存儲著各種常量赎瞎,其中存儲字符串常量的區(qū)域被習慣地稱為字符串池(String Pool)牌里。在第一個例子中,有兩個“hello world”常量务甥,但是在常量池中牡辽,只會創(chuàng)建一個常量,也就是說敞临,在編譯好的 class 文件中态辛,只能找到一個“hello world”常量。因此 s1 和 s2 指向的在常量池中同一個字符串對象挺尿,“==”比較是否是同一個對象奏黑,所以結(jié)果返回 true炊邦。
擴展知識
private final char value[];
字符串是用一個不可變的字符數(shù)組來存儲字符串內(nèi)容,當 String 對象創(chuàng)建之后熟史,就不能修改對象中存儲的內(nèi)容馁害,所以說,String 類型是不可變的(immutable)
例如
String s1 = new String("hello");
s1 = s1 + " world";
因為 String 是不可變的蹂匹,這段代碼會根據(jù)s1的內(nèi)容和字符串常量“ world”在heap區(qū)創(chuàng)建一個新的字符串
String s1 = new String("hello world");
該語句創(chuàng)建兩個 String 對象碘菜,一個是在編譯時,創(chuàng)建于字符串常量區(qū)限寞,一個是在運行時忍啸,創(chuàng)建于heap區(qū)。
Java對String進行了“+”操作符重載履植,利用“+”可以將字符串連接计雌。但是需要注意的是
String s1 = "hello" + " world";
該代碼與第一點的例子不一樣,編譯時編譯器會直接提取兩個常量的內(nèi)容玫霎,只生成“hello world”一個字符串凿滤,同理,無論多少個常量相加鼠渺,都是生成一個對象鸭巴。
運行時調(diào)用 String 的 intern() 方法可以向 String Pool 中動態(tài)添加對象。
5.String創(chuàng)建的幾種方法
- 使用“”拦盹。
- 使用 new String();
- 使用 new String("hello world");
- 使用重載操作符“+”
StringBuffer&StringBuilder
StringBuilder一個可變的字符序列是5.0新增的鹃祖。此類提供一個與 StringBuffer 兼容的 API,但不保證同步普舆。該類被設(shè)計用作 StringBuffer 的一個簡易替換恬口,用在字符串緩沖區(qū)被單個線程使用的時候(這種情況很普遍)。如果可能沼侣,建議優(yōu)先采用該類祖能,因為在大多數(shù)實現(xiàn)中,它比 StringBuffer 要快蛾洛。
Stringbuffer 和 StringBuilder除了線程安全的區(qū)別外养铸,其他基本一致,都繼承于AbstractStringBuffer轧膘。
來看一下AbstractStringBuffer的源碼
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;
/**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}
/**
* Creates an AbstractStringBuilder of the specified capacity.
*/
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
/**
* Returns the length (character count).
*
* @return the length of the sequence of characters currently
* represented by this object
*/
@Override
public int length() {
return count;
}
/**
* Returns the current capacity. The capacity is the amount of storage
* available for newly inserted characters, beyond which an allocation
* will occur.
*
* @return the current capacity
*/
public int capacity() {
return value.length;
}
AbstractStringBuffer 使用的是可變的char數(shù)組钞螟,在創(chuàng)建 StringBuffer 和 StringBuilder 時有幾種方式,其中無參的構(gòu)造方法調(diào)用的是父類的構(gòu)造方法谎碍,創(chuàng)建大小為16的char數(shù)組
public StringBuffer() {
super(16);
}
public StringBuilder() {
super(16);
}
其他的構(gòu)造方法鳞滨,StringBuilder 與之類似
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public StringBuffer(CharSequence seq) {
this(seq.length() + 16);
append(seq);
}
其他常見方法:append、insert
三者區(qū)別
可變性
String 不可變蟆淀,StringBuffer拯啦、StringBuilder可變
速度
StringBuilder > StringBuffer > String
線程安全
String澡匪、StringBuilder不安全,StringBuffer安全
總結(jié)
- 在編譯階段就能夠確定的字符串常量褒链,完全沒有必要創(chuàng)建String或StringBuffer對象唁情。直接使用字符串常量的"+"連接操作效率最高。
- StringBuffer對象的append效率要高于String對象的"+"連接操作碱蒙。
- 不停的創(chuàng)建對象是程序低效的一個重要原因荠瘪。那么相同的字符串值能否在堆中只創(chuàng)建一個String對象那。顯然拘留字符串能夠做到這一點赛惩,除了程序中的字符串常量會被JVM自動創(chuàng)建拘留字符串之外,調(diào)用String的intern()方法也能做到這一點趁餐。當調(diào)用intern()時喷兼,如果常量池中已經(jīng)有了當前String的值,那么返回這個常量指向拘留對象的地址后雷。如果沒有季惯,則將String值加入常量池中,并創(chuàng)建一個新的拘留字符串對象臀突。