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