科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道全面解析Java中的String数据类型

全面解析Java中的String数据类型

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

全面解析Java中的String数据类型

作者: kqlove2008 来源:赛迪网技术社区 2007年11月29日

关键字: 类型 string 解析

  • 评论
  • 分享微博
  • 分享邮件
1. 首先String不属于8种基本数据类型,String是一个对象。 \y YSotg  
`<a%,$+oS|  
因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。 k $ S'KDE  
=ty`L6l\  
2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null; N%zt*& U  
>!/j hn  
3. String str=”kvill”; &qm>q5LY1<  
c8=+2 n  
String str=new String (“kvill”);的区别: -JoyEj))  
[fPS{-  
在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。 $p<PYH^G  
/7Pyeh,W  
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。 9!jKl5nn  
,R2sa&I  
看例1: ] 5im{do&5  
r)P}U"n  
String s0=”kvill”; 3&1IZ@Vn=  
>Ut(PvIp  
String s1=”kvill”; JB#WG3$4  
miCAe.0*  
String s2=”kv” + “ill”; qfq_ o[CIN  
Fqh~FY5  
System.out.println( s0==s1 ); r2AsldB1  
ErNZ|`_  
System.out.println( s0==s2 ); .VV2~S6  
结果为: |}68'Bk  
Hd#4i  
true 0tX:V]  
e#-yYHYb  
true rer1;0=Q0@  
-5X!Ub`  
首先,我们要知结果为道Java会确保一个字符串常量只有一个拷贝。 6'[;iNO:  
pXs>byW0?  
因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。 8h&:Y:U4  
.2F$9  
所以我们得出s0==s1==s2; \2p;:W/z  
J$'X/!c5  
用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。 r]--gZv^@H  
T: LDlK  
看例2: AbyCTL'  
& rA"^o  
String s0=”kvill”; 6k]'z,eeA  
3Fk*\uvMT  
String s1=new String(”kvill”); wS5`@L  
Mzkp^>PC  
String s2=”kv” + new String(“ill”); WQ[-Y*[*  
cGyh[Or?g  
System.out.println( s0==s1 ); N@eaUq  
G6<~yg0  
System.out.println( s0==s2 ); & BaXO  
!8RN%8|Z  
System.out.println( s1==s2 ); 结果为: nu|1 zOzH  
oRqp@kp t  
false C:BF3  
Q45vuH4{!  
false Z^l&F%x  
&Af?Wu,MR  
false kSb ,m!{  
例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。 51#X? QM8  
05= Cn{  
4. String.intern(): ;@ _X8Cx#  
t!OXBZj  
再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看例3就清楚了 O>pgL0~bZ  
o[]uxxQi  
例3: a<#X (.5wo  
>;2<vx\  
String s0= “kvill”; @sOl bE  
"!tB^Rv^D  
String s1=new String(”kvill”); 6*La n[  
Bc8 ;3l/Q  
String s2=new String(“kvill”); *"n^ x]  
_tSR9FU75>  
System.out.println( s0==s1 ); 2o.o$'r  
l(A<5b7[c  
System.out.println( “**********” ); /)Cm-DF  
PQSz~`  
s1.intern(); 's$Zq>fJ  
UOB \t(f  
s2=s2.intern(); //把常量池中“kvill”的引用赋给s2 E4pFV/7[m  
Lq"lzT,X#$  
System.out.println( s0==s1); 8>|7+:Klt  
sLXF]P>C  
System.out.println( s0==s1.intern() ); q{!G@UN;  
])Tf9Sz  
System.out.println( s0==s2 ); nfyx \  
 ?mH!-eW  
结果为: xvr-]9E  
FX\oyt=`Z  
false 8uzcYOq:  
XK=V|yVTg  
********** W;&#/^  
&O^:\y{Mm  
false //虽然执行了s1.intern(),但它的返回值没有赋给s1 J$-*S";  
<-5 ]x"!  
true //说明s1.intern()返回的是常量池中”kvill”的引用 FBXZ83 y  
ej0T!s:k  
true 7}r :D |L  
+W7XX.!>  
最后我再破除一个错误的理解: 9,l~@Ag  
5zfp!}H  
有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的: +wE U"4  
<Rp@^aK  
看例4: ze1)QW<W  
F_H-ou]  
String s1=new String("kvill"); w"kvw`(b  
'L0b2I<>s  
String s2=s1.intern(); 9 G>Zq ~  
46`?+!  
System.out.println( s1==s1.intern() ); J\+ 9Jfnr  
fBYF_ "6W  
System.out.println( s1+" "+s2 ); ]Ju5Vu80  
Ss ] PWN  
System.out.println( s2==s1.intern() ); -s-*pfFh  
C#M)lYl  
结果: (p}]]^A,  
NqN18 #>  
false InyDfAMFI  
>(3 B :^  
kvill kvill }dOn=iw~V  
9c&RR  
true LdD/ci^+{  
6mvrq}?J#@  
^{~-9.  
在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。 >#|_eX~p +  
10w&)m%  
s1==s1.intern()为false说明原来的“kvill”仍然存在; GO^! R xKj  
;KlY  
s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。 p0)aT`u  
J;M#"~aL  
5. 关于equals()和==: s>0#0(l1^  
OV Xf f;  
这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。 *AU&kzM  
z\eru+w)  
6. 关于String是不可变的 78@[7B+>  
W6e6UR)3<  
这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”; 'I`P$BH  
n,r\{%~- v  
就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的。 VC_P?}/u>  
Ei2vY<2  
文字 查看本文来源
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章