首页 > 代码库 > Java中的String
Java中的String
参考资料:
http://www.cnblogs.com/chenssy/p/3695271.html
http://blog.csdn.net/yyaf2013/article/details/12168491
首先先来看看下面这段代码的输出结果:
public void strTest() { String a = "huhui"; String b = "huhui"; String c = new String("huhui"); System.out.println("a == b? "+(a == b)); System.out.println("a == c? "+(a == c)); System.out.println("a.equals(b)? "+a.equals(b)); System.out.println("a.equals(c)? "+a.equals(c)); }output:
a == b? true a == c? false a.equals(b)? true a.equals(c)? true
有人可能要问,为什么a==b的结果是true呢?先来看看"=="和equals的区别:
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("123"); String b=new String("123");两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有重写equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){ return this==o; }这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,
现在来分析strTest()方法的执行结果:
字符串的分配和其他对象分配一样,是需要消耗时间和空间的,而且字符串我们使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串(这点对理解上面至关重要)。
String a = "huhui";
String b = "huhui";
上面两条语句中,a和b都是指向JVM字符串常量池中的"huhui"对象,他们指向同一个对象,故表达式a==b返回true。
String c = new String("huhui");
上面这条语句,new关键字产生了一个对象"huhui"(注意这个huhui和上面的huhui不同),由于是new产生的对象,所以这个对象是存储在堆中。于是上面的语句产生了两个对象:保存在栈中的c和保存在堆中的"huhui。但是在Java中不会存在两个完全一模一样的字符串对象。故堆中的"huhui"是引用字符串常量池中的"huhui",所以c、huhui、池huhui的关系应该是:c-->huhui-->池huhui。整个关系如下:
图片来源:http://www.cnblogs.com/chenssy/p/3695271.html
通过上面的图我们可以清楚的看到a、b、c、"huhui"之间的关系。String c = new String("huhui");虽然c的内容是创建在堆中,但是他的内部value还是指向JVM常量池的huhui的value,它构造huhui时所用的参数依然是huhui字符串常量。
Java中的String