java语言中String类源代码的深入研究
吴道荣 吴道勇
摘 要:在java程序设计中,有百分之五六十的代码是和字符串打交道,文章针对String类toString()方法、equals()方法源代码进行分析,从典型案例中详述String类的String Pool中对象和heap中对象,论述清楚String类中一些很难理解的“陷阱”和知识难点。
关键词: Java Web编程对象toString方法equals方法
一、引言
在java程序设计中,有百分之五六十的代码是和字符串打交道,因此String类在java基础知识中显得尤其重要,而String中的一些知识点又有一些“陷阱”较难理解,本文将对其进行分析研究。
二、String类
String类代表字符串。Java程序中的所有字符串字面值(如“abc”)都作为此类的实例。
字符串是常量,它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为String对象是不可变的,所以可以共享。例如:
String str="abc";
等效于:
char data[]={‘a’,‘b’,‘c’};
String str= new String(data);
String是常量,其对象一旦创建完毕就无法改变。当使用“+”拼接字符串时,会生成新的String对象,而不是向原有的String对象追加内容。
Java程序中底层代码有一些“陷阱”,如果不清楚底层代码的编写,就很难搞清楚一些比较典型的程序的结论。
三、String类的toString()分析
(一)程 序
public class ObjectTest
{
public static void main(String[]args)
{
Object object= new Object();
System.out.println(object);
System.out.println(object. toString());
String str="aaa";
System.out.println(str);
System.out.println(str. toString());
Student student= new Student();
System.out.println(student);
System.out.println(student. toString());
}
}
class Student extends Object
{
public StringtoString()
{
return"Hello World";
}
}
(二)分析
当将对象传递给print方法和println方法时,将自动调用一个to String,以获得被打印对象的字符串形式的描述。实际上会打印出引用所指对象的to String()方法的返回值,因为每个类都直接或间接地继承自Object,而Object类中定义了to String(),因此每个类都有to String()这个方法。
通常,to String方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
1.Object类中的public String to String()方法
Object类中的public String to String()返回该对象的字符串表示。
Object类的to String方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
get Class( ).get Name( )+‘@’+ Integer. to Hex String(hash-Code( ))
程序中:
System.out.println(object);和System.out.println(object.to String( ));是等价的。
输出的结果都是:
java.lang.Object@ de6ced
它们调用的是Object定义的to String方法。
2.String类中的public String to String()方法
String类中的public String to String()返回此对象本身(它已经是一个字符串)。
程序中:
System.out.println(str);和System.out.println(str. to String());是等价的。
输出的结果都是:
aaa
它们调用的toString方法不是Object定义的to String方法,而是String类定义的to String方法。
3.自己定义类中的public String to String()方法
程序中:
System.out.println(student);和System.out.println(student.to String());是等价的。
输出的结果都是:
Hello World
它调用的to String方法是在本程序Student类自己定义的to String方法。Student类自己定义的to String方法返回“Hello World”字符串。
四、String类的equals( )方法和“==”分析
(一)程 序
public class String Test
{
public static void main(String[]args)
{
String str1= new String("aa");
String str2= new String("aa");
System.out.println(str1.equals(str2));
String str3="aa";
String str4="aa";
System.out.println(str3.equals(str4));
Object object1= new Object();
Object object2= new Object();
System.out.println(object1.equals(object2));
System.out.println(object1.equals(object1));
}
}
(二)分 析
1.String类的equals()方法和“==”
对于String类的equals()方法来说,它主要是用来判断当前字符串与传进字符的内容是否一致。对于String对象的相等性判断来说,请使用equals()方法,而不要使用“==”。
String类equals方法的源代码:
publicboolean equals(Object an Object)
{
if(this== an Object)
{ (www.xing528.com)
return true;
}
if(an Object instance of String)
{
Stringanother String=(String) an Object;
int n= count;
if(n== another String. count)
{
char v1[]= value;
char v2[]= another String.value;
int i= offset;
int j= another String.offset;
while(n--!= 0)
{
if(v1[i++]!= v2[j++])
return false;
}
return true;
}
}
return false;
}
程序中,System.out.println(str1.equals(str2));输出的结果是: true; System.out.println(str3.equals(str4));输出的结果是: true。
2.Object类的equals()方法和“==”
Object类当中定义了equals()方法,因此java中的每个类都具有该方法,对于Object类的equals()方法来说,它是用来判断调用equals()方法的引用与传进来引用是否一致,即这两个引用指向的对象。对于Object类的equals()方法来说,它等价于“==”。
Object类equals方法的源代码:
publicboolean equals(Object obj)
{
return(this== obj);
}
程序中,System.out.println(object1.equals(object2));输出的结果是: false; System.out.println( object1.equals(object2));输出的结果是: true。
五、String类的String Pool中对象和heap中对象的分析
(一)程 序
public class ObjectTest2
{
public static void main(String[]args)
{
Object object1= new Object();
Object object2= new Object();
System.out.println(object1== object2);
String str1= new String("wang");
String str2= new String("wang");
System.out.println(str1== str2);
String str3="zhang";
String str4="zhang";
System.out.println(str3== str4);
String str5= new String("zhao");
String str6="zhao";
System.out.println(str5== str6);
String str7="hello";
String str8="hel";
String str9="lo";
System.out.println(str7== str8+ str9);
System.out.println(str7=="hel"+"lo");
}
}
(二)分 析
1.相等性的比较(= =)
(1)对于原生数据类型来说,比较的是左右两边值是否相等。
(2)对于引用类型来说,比较左右两边是否指向同一个对象或者两边的引用地址是否相同。
程序中,System.out.println(object1== object2);是对于引用类型的比较。Object1、object2分别指向heap中两个不同对象的地址。输出的结果是: false。
程序中,System.out.println(str1== str2);也是对于引用类型的比较。Str1、str2分别指向heap中两个不同对象的地址。输出的结果是: false。
2.String Pool(字符串池)
(1) String s=“aaa”;(采用字面值方式赋值)。
①查找String Pool中是否存在“aaa”这个对象,如果不存在这个对象,则在String Pool中创建一个“aaa”对象,然后将String Pool中的这个“aaa”对象的地址返回来,赋给引用变量s,这样s会指向String Pool中的这个“aaa”字符串对象。
②如果存在,则不创建任何对象直接将String Pool中的这个“aaa”对象地址返回来,赋给s引用。
程序中,System.out.println(str3== str4);的str3、str4指向String Pool中同一个对象“zhang”的地址。输出的结果是: true。
(2) String s= new String(“aaa”)。
①首先在String Pool中查找有没“aaa”这个字符串对象,如果有则不在String Pool中再去创建“aaa”这个对象了,直接在堆(heap)中创建一个“aaa”字符串对象,然后将堆中的这个“aaa”对象的地址返回来,赋给s引用,导致s指向了堆中创建的这个“aaa”字符串对象。
②如果String Pool中没有“aaa”这个字符串对象,则首先在String Pool中创建一个“aaa”对象,然后再在堆(heap)中创建一个“aaa”对象,然后将堆中的这个“aaa”对象的地址返回来,赋给s引用,导致s指向了堆中所创建的这个“aaa”对象。
程序中,System.out.println(str5== str6);的str5指向heap中的“zhao”地址,str6指向String Pool中“zhao”的地址。输出的结果是: false。
(3) String类的intern方法。
String类的intern方法返回字符串对象的规范化表示形式。
一个初始为空的字符串池,它由类String独自维护。
当调用intern方法时,如果String Pool中已经包含一个等于此String对象的字符串[用equals(Object)方法确定],则返回池中的字符串。否则,将此String对象添加到String Pool中,并返回此String对象的引用。
它遵循以下规则:对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s. intern()== t. intern()才为true。
所有字面值字符串和字符串赋值常量表达式都使用intern方法进行操作。
程序中,System.out.println(str7== str8+ str9);的str7指向String Pool中的“hello”对象,str8指向heap中的“hel”对象,str9指向heap中的“lo”对象,而str8+ str9在heap中生成了另一个对象,等价于new String(“hello”)。输出的结果是: false。
程序中,System.out.println(str7== str8+ str9);的str7指向String Pool中的“hello”对象,“hel”是String Pool中的对象,“lo”也是String Pool对象,而str8+ str9就返回String Pool中的“hello”对象。输出的结果是: true。
六、结束语
文章深入String类toString()方法、equals()方法对源代码进行分析,从典型案例中详述String类的String Pool中对象和heap中对象,论述清楚String类中一些很难理解的“陷阱”和知识难点,解决在使用String类时的一些实际问题。
参考文献:
[1]John Lewis William Loftus. Java程序设计教程[M].北京:电子工业出版社,2009.
[2]李芝兴,杨瑞龙. Java程序设计之网络编程:第2版[M].北京:清华大学出版社,2009.
[3]林信良. JDK 6 Java学习笔记[M].北京:清华大学出版社,2007.
[4]阎宏. Java与模式[M].北京:电子工业出版社,2002.
[5]李斌,王睿,何成芊.深入探讨Java中的String类[J].长沙通信职业技术学院学报,2009(9).
[6]张建东. Java程序设计教学探讨[J].科技信息,2009(8).
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。