之前关于String的理解仅限于三点:
一、String 是final类,不可继承
二、String 类比较字符串相等时时不能用“ == ”,只能用 "equals"
三、String 类不可更改
String 使用很是方便,所以通常涉及字符串时都用该类进行字符串处理
至于String类的类在机制,则极少去探究。
直到读到下面这个例子。
class
X
{
public
static
String strX
=
"
hello
"
;
}
class
Y
{
public
static
String strY
=
"
hello
"
;
}
class
Z
{
public
static
String strZ
=
"
hell
"
+
"
o
"
;
}
class
Test
{
public
static
void
main(String[] args)
{
System.out.println( X.strX
==
Y.strY);
System.out.println( X.strX
==
Z.strZ);
String s1
=
"
hel
"
;
String s2
=
"
lo
"
;
System.out.println( X.strX
==
(s1
+
s2));
System.out.println( X.strX
==
(s1
+
s2).intern());
}
}
按照个人理解,类X,类Y,类Z中的三个常量字符串属于不一样的对象,用 == 操做符比较,那么结果必然是 false,输出应该为:
false
false
false
false
但实际上输出确是:
true
true
false
true
使我大惑不解。并所以找了许多资料来看(尤为是C++和Java比较编程,里面解释比较详细),终于逐渐明白了缘由。
== 只有在两个比较对象指向同一对象时,其值才为true。
X.strX
==
Y.strY 与
X.strX
==
Z.strZ 测试结果都为true,说明这三个常量指向的都是同一个对象。
在JAVA中,
String
是字符串常量。由相同序列的字符组成的两个字符串属于同一对象,位于内存中的同一个位置。每一个字符串常量只有一个 String 对象来表示。即便这个字符串常量出如今一个程序的不一样位置甚至一个程序的不一样程序包中。也就是说,
X.strX 与
Y.strY 因为都是同一字符序列,所以 指向的确定是同一对象。
Z.strZ 也是如此。"hell"+"o",两个常量字符串相加后,建立了一个新的字符串常量(这个工做是编译期间完成的),它与
X.strX ,
Y.strY有相同的字符序列,所以指向同一对象
。
虽然一个常量表达式将两个字符串常量连接在一块儿的结果在编译器已完成,可是
String s1="hel";
String s2="lo";
String s3=s1+s2;
这段代码中,s3只能在运行期间建立。这三条语句所建立的"hello"字符串做为String对象存储在内存中的一个独立位置。
Java提供一个机制,经过String类定义的intern()方法把
一个运行时建立的字符串加到字符串常量池(若是它尚未入池)。若是上面的三条代码改成:
String s1="hel";
String s2="lo";
String s3=(s1+s2).intern();
java将把 s1+s2 所返回的字符串对象中的字符序列与已经存储在字符串常量池中的字符串进行比较。若是找到一个匹配,intern()就返回这个字符串的引用。若是没有找到匹配,
s1+s2 所返回的字符串将被加入到字符串常量池中,并返回这个字符串常量的引用。
这就解释了为社么X.strX==(s1+s2)返回false,而X.strX==(s1+s2).intern()返回true。
(s1+s2).intern()指向strX,strY,StrX指向的字符串常量"hello"。