首先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;
Systemoutprintln( s==s );
Systemoutprintln( 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的應用;明白了這些也就知道為何得出此結果了
Stringintern()
再補充介紹一點存在於class文件中的常量池在運行期被JVM裝載並且可以擴充String的intern()方法就是擴充常量池的一個方法當一個String實例str調用intern()方法時Java查找常量池中是否有相同Unicode的字符串常量如果有則返回其的引用如果沒有則在常量池中增加一個Unicode等於str的字符串並返回它的引用看例就清楚了 [Page]
例
String s= kvill;
String s=new String(kvill);
String s=new String(kvill);
Systemoutprintln( s==s );
Systemoutprintln( ********** );
sintern();
s=sintern(); //把常量池中kvill的引用賦給s
Systemoutprintln( s==s);
Systemoutprintln( s==sintern() );
Systemoutprintln( s==s );
結果為
false
**********
false //雖然執行了sintern()但它的返回值沒有賦給s
true //說明sintern()返回的是常量池中kvill的引用
true
最後我再破除一個錯誤的理解
有人說使用Stringintern()方法則可以將一個String類的保存到一個全局String表中
如果具有相同值的Unicode字符串已經在這個表中那麼該方法返回表中已有字符串的地址
如果在表中沒有相同值的字符串則將自己的地址注冊到表中
如果我把他說的這個全局的String表理解為常量池的話他的最後一句話如果在表中沒有相同值的字符串則將自己的地址注冊到表中是錯的
看例
String s=new String(\kvill\);
String s=sintern();
Systemoutprintln( s==sintern() );
Systemoutprintln( s+\ \+s );
Systemoutprintln( s==sintern() );
結果
false
kvill kvill
true
在這個類中我們沒有聲名一個kvill常量所以常量池中一開始是沒有kvill的
當我們調用sintern()後就在常量池中新添加了一個kvill常量原來的不在常量池中的kvill仍然存在也就不是將自己的地址注冊到常量池中了
s==sintern()為false說明原來的kvill仍然存在
s現在為常量池中kvill的地址所以有s==sintern()為true
關於equals()和==:
這個對於String簡單來說就是比較兩字符串的Unicode序列是否相當如果相等返回true;而==是比較兩字符串的地址是否相同也就是是否是同一個字符串的引用
關於String是不可變的
這一說又要說很多大家只要知道String的實例一旦生成就不會再改變了 [Page]
比如說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/28332.html