首先String不屬於
種基本數據類型
String是一個對象
因為對象的默認值是null
所以String的默認值也是null
但它又是一種特殊的對象
有其它對象沒有的一些特性
new String()和new String(
)都是申明一個新的空字符串
是空串不是null
String str=
kvill
String str=new String (
kvill
);的區別
在這裡
我們不談堆
也不談棧
只先簡單引入常量池這個簡單的概念
常量池(constant pool)指的是在編譯期被確定
並被保存在已編譯的
class文件中的一些數據
它包括了關於類
方法
接口等中的常量
也包括字符串常量
看例
String s
=
kvill
;
String s
=
kvill
;
String s
=
kv
+
ill
;
System
out
println( s
==s
);
System
out
println( s
==s
);
結果為
true
true
首先我們要知結果為道Java會確保一個字符串常量只有一個拷貝
因為例子中的s和s中的kvill都是字符串常量它們在編譯期就被確定了所以s==s為true而kv和ill也都是字符串常量當一個字符串由多個字符串常量連接而成時它自己肯定也是字符串常量所以s也同樣在編譯期就被解析為一個字符串常量所以s也是常量池中kvill的一個引用
所以我們得出s==s==s; 用new String() 創建的字符串不是常量不能在編譯期就確定所以new String() 創建的字符串不放入常量池中它們有自己的地址空間
看例
String s=kvill;
String s=new String(kvill);
String s=kv + new String(ill);
Systemoutprintln( s==s );
Systemoutprintln( s==s );
Systemoutprintln( s==s );
結果為
false
false
false
例
中s
還是常量池中
kvill
的應用
s
因為無法在編譯期確定
所以是運行時創建的新對象
kvill
的引用
s
因為有後半部分new String(
ill
)所以也無法在編譯期確定
所以也是一個新創建對象
kvill
的應用;明白了這些也就知道為何得出此結果了
String
intern()
再補充介紹一點
存在於
class文件中的常量池
在運行期被JVM裝載
並且可以擴充
String的intern()方法就是擴充常量池的一個方法
當一個String實例str調用intern()方法時
Java查找常量池中是否有相同Unicode的字符串常量
如果有
則返回其的引用
如果沒有
則在常量池中增加一個Unicode等於str的字符串並返回它的引用
看例
就清楚了
例
String s
=
kvill
;
String s
=new String(
kvill
);
String s
=new String(
kvill
);
System
out
println( s
==s
);
System
out
println(
**********
);
s
intern();
s
=s
intern(); //把常量池中
kvill
的引用賦給s
System
out
println( s
==s
);
System
out
println( s
==s
intern() );
System
out
println( s
==s
);
結果為
false
**********
false //雖然執行了s
intern()
但它的返回值沒有賦給s
true //說明s
intern()返回的是常量池中
kvill
的引用
true
最後我再破除一個錯誤的理解
有人說
使用String
intern()方法則可以將一個String類的保存到一個全局String表中
如果具有相同值的Unicode字符串已經在這個表中
那麼該方法返回表中已有字符串的地址
如果在表中沒有相同值的字符串
則將自己的地址注冊到表中
如果我把他說的這個全局的String表理解為常量池的話
他的最後一句話
如果在表中沒有相同值的字符串
則將自己的地址注冊到表中
是錯的
看例
String s
=new String(
kvill
);
String s
=s
intern();
System
out
println( s
==s
intern() );
System
out
println( s
+
+s
);
System
out
println( s
==s
intern() );
結果
false
kvill kvill
true
在這個類中我們沒有聲名一個kvill常量所以常量池中一開始是沒有kvill的當我們調用sintern()後就在常量池中新添加了一個kvill常量原來的不在常量池中的kvill仍然存在也就不是將自己的地址注冊到常量池中了
s==sintern()為false說明原來的kvill仍然存在s現在為常量池中kvill的地址所以有s==sintern()為true
關於equals()和==:
這個對於String簡單來說就是比較兩字符串的Unicode序列是否相當如果相等返回true;而==是比較兩字符串的地址是否相同也就是是否是同一個字符串的引用
關於String是不可變的
這一說又要說很多大家只要知道String的實例一旦生成就不會再改變了比如說String str=kv+ill+ +ans;
就是有個字符串常量首先kv和ill生成了kvill存在內存中然後kvill又和 生成 kvill 存在內存中最後又和生成了kvill ans;並把這個字符串的地址賦給了str就是因為String的不可變產生了很多臨時變量這也就是為什麼建議用StringBuffer的原因了因為StringBuffer是可改變的
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28153.html