Java中的equals和==,字符串常量池介绍

出处:http://blog.csdn.net/seu_calvin/article/details/52089040

http://www.jb51.net/article/59935.htm

1.  Java中数据类型分类

1.1    基本数据类型

又称为原始数据类型,byte,short,char,int,long,float,double,boolean,他们之间的比较应该使用(==),比较的是他们的值。


1.2    复合数据类型

当复合数据类型用(==)进行比较,比较的是他们在内存中的存放地址。

当复合数据类型之间进行equals比较时,这个方法的初始行为是比较对象在堆内存中的地址,但在一些诸如String,Integer,Date类中把Object中的这个方法覆盖了,作用被覆盖为比较内容是否相同。



2.  String类的讨论

[java] view plain copy
  1. String s1 = "Hello";  
  2. String s2 = "Hello";  
  3. if (s1 == s2){  
  4.  System.out.println("s1 == s2");  
  5. }else{  
  6. System.out.println("s1 != s2");  
  7. }  
输出:s1 == s2

说明:双等号在进行复合数据类型比较时,比较的是内存中的存放地址。因此s1与s2引用同一个String对象。

[java] view plain copy
  1. String s1 = "Hello";  
  2. String s2 = new String("Hello");  
  3. if (s1 == s2){  
  4. System.out.println("s1 == s2");  
  5. }else{  
  6. System.out.println("s1 != s2");  
  7. }  
  8. if (s1.equals(s2)) {  
  9. System.out.println("s1 equals s2");  
  10. }else{  
  11. System.out.println("s1 not equals s2");  
  12. }  

输出:
s1 != s2
s1 equals s2
说明:s1 s2分别引用了两个对象。显然,两者内容是相同的,因此equal返回true。第一个例子也一样。

我们接下来将详细讨论,为什么在上面两个例子中,s1和s2出现了两种不同的指向对象的情况。


3.   解释

[java] view plain copy
  1. String str = new String("abc");   
  2. String str = "abc";   

String str = new String("abc")创建实例的过程 1 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象 2 在字符串常量池中查看,是否存在内容为"abc"字符串对象引用 3 若存在,则将new出来的字符串对象与字符串常量池中的对象引用联系起来 4 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象引用,并将堆中的对象与之联系起来,如果常量池中已经存在"abc",那么就不会额外在常量池中生成引用。因此这个语句会产生一个或者两个对象。


String str = "abc"创建对象的过程 1 首先在常量池中查找是否存在内容为"abc"字符串对象引用 2如果不存在,那么会创建这个字符串对象,然后将刚创建的对象的引用放入到字符串常量池中,并且将引用返回给变量str1 3 如果存在则直接让str引用该对象。 

由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。 

具体可以查看此篇String、StringBuider以及StringBuffer的区别和使用场景


4.  String类的intern方法

[java] view plain copy
  1. String s1 = "Hello";  
  2. String s2 = new String("Hello");  
  3. s2 = s2.intern();  
  4. if (s1 == s2){  
  5. System.out.println("s1 == s2");  
  6. }else{  
  7. System.out.println("s1 != s2");  
  8. }  
  9. if (s1.equals(s2)) {  
  10. System.out.println("s1 equals s2");  
  11. }else{  
  12. System.out.println("s1 not equals s2");  
  13. }  

程序输出:
s1 == s2
s1 equals s2
这次加入:s2 = s2.intern(),java.lang.String的intern()方法,"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作:检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。但是这也仅仅是JDK1.6以及以前的过时的处理方法,如果想了解更全更清晰的intern()方法,请务必参考我的这篇博文Java技术——你真的了解String类的intern()方法吗


5.  为什么Java中1000==1000为false而100==100为true?

[java] view plain copy
  1. Integer i1 = 100,i2 = 100;  
  2. System.out.println(i1==i2);  
  3. Integer i3 = 1000,i4 = 1000;  
  4. System.out.println(i3==i4);  

查看Integer.java类,会发现有一个内部私有类,IntegerCache.java,它缓存了从-128到127之间的所有的整数对象。

所以例子中i1和i2指向了一个对象。因此100==100为true。


6.  字符串常量池

JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池(存在于方法区的常量池中)。


字符串常量池存放的是对象引用,不是对象。在Java中,对象都创建在堆内存中。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值