java中equals和==的区别

来源:互联网 发布:小意思 mac 编辑:程序博客网 时间:2024/06/05 23:43

值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

==比较的是2个对象的地址,而equals比较的是2个对象的内容。
显然,当equalstrue时,==不一定为true

一、String中的equals==
1
public class TestString {
     public static void main(String[] args) {
         String s1 = "Monday";
         String s2 = "Monday";
     }
}
上面这段程序中,到底有几个对象呢?
来检测一下吧,稍微改动一下程序
public class TestString {
     public static void main(String[] args) {
         String s1 = "Monday";
         String s2 = "Monday";
         if (s1 == s2)
             System.out.println("s1 == s2");
         else
             System.out.println("s1 != s2");
     }
}

编译并运行程序,输出:s1 == s2
说明:s1 与 s2 引用同一个 String 对象 -- "Monday"!

2.
再稍微改动一下程序,会有更奇怪的发现:
public class TestString {
     public static void main(String[] args) {
         String s1 = "Monday";
         String s2 = new String("Monday");
         if (s1 == s2)
             System.out.println("s1 == s2");
         else
             System.out.println("s1 != s2");
         if (s1.equals(s2))
             System.out.println("s1 equals s2");
         else
             System.out.println("s1 not equals s2");
     }
}
我们将 s2 用 new 操作符创建
程序输出:
s1 != s2
s1 equals s2
说明:s1 s2分别引用了两个"Monday"String对象

3. 字符串缓冲池

原来,程序在运行的时候会创建一个字符串缓冲池
当使用 s2 = "Monday" 这样的表达是创建字符串的时候,程序首先会
在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被
放到了池中,所以在s2被创建的时候,程序找到了具有相同值的 s1
将 s2 引用 s1 所引用的对象"Monday"
第二段程序中,使用了 new 操作符,他明白的告诉程序:
"我要一个新的!不要旧的!"于是一个新的"Monday"Sting对象被创
建在内存中。他们的值相同,但是位置不同,一个在池中游泳
一个在岸边休息。哎呀,真是资源浪费,明明是一样的非要分开做什么呢?
4. 
再次更改程序:
public class TestString {
     public static void main(String[] args) {
         String s1 = "Monday";
         String s2 = new String("Monday");
         s2 = s2.intern();
         if (s1 == s2)
             System.out.println("s1 == s2");
         else
             System.out.println("s1 != s2");
         if (s1.equals(s2))
             System.out.println("s1 equals s2");
         else
             System.out.println("s1 not equals s2");
     }
}
这次加入:s2 = s2.intern();
程序输出:
s1 == s2
s1 equals s2

原来,(java.lang.Stringintern()方法 
"abc".intern()方法的返回值还是字符串"abc",表面上看起来好像这个方法没什么用处。但实际上,它做了个小动作: 
检查字符串池里是否存在"abc"这么一个字符串,如果存在,就返回池里的字符串;如果不存在,该方法会把"abc"添加到字符串池中,然后再返回它的引用。

更好的办法:
把所有的Stringintern()到缓冲池去吧
最好在用到new的时候就进行这个操作
String s2 = new String("Monday").intern();
然后就可以用==比较两个字符串的值了


二、简单数据类型和封装类中的equals==
Java为每一个简单数据类型提供了一个封装类,每个基本数据类型可以封装成对象类型。 
intInteger)和charCharacter),其余类型首字母大写即成封装类类型名。double (Double), float(Float),long(Long), short(Short),byte(Byte),boolean(Boolean).
  
intInteger为例说明 
JavaintInteger区别如下:
1.int是基本的数据类型,默认值可以为0
2.Integerint的封装类,默认值为null
3.intInteger都可以表示某一个数值;
4.intInteger不能够互用,因为他们两种不同的数据类型;
int a1=1;
int a2=1;
Integer b1 =new Integer (1);
Integer b2 =new Integer (1);
------------------------------
a1==a2 这个是成立的,很简单,都知道
a1==b1 这个是不成立的.表达式的值为 false ,它们是不同的数据类型(在jdk1.5以上版本中为true
b1==b2 这个也是不成立的.表达式的值为 false,虽然是相同的数据类型,但是它们是两个对象,==比较的是2个对象的地址,它们的地址是不相等的,内容相等都是1;
b1.equals(b2)==true 这个是成立的,表达式的值为 true. 相同数据类型,两个对象,地址不同,内容相同, quals比较的是2个对象的内容,所以成立。
(a.equals(b),因为equals比较的是两个对象,所以a,b都不能为基本数据类型,否则会出编译错误。)(在jdk1.5以上版本中,b可以为基本数据类型,a不可以)
同理,其它的封装类和基本类型也是这样的.
javaequals==的区别
==比较的是2个对象的地址,而equals比较的是2个对象的内容。

jdk1.5以上的版本中,基本类型和封装类能自动转化,与String类型的对象和字符串常量类似。
        Integer i1 = 123;
        Integer i2 = 123;
        
        int i = 123;
        
        Integer i3 = new Integer(123);
        Integer i4 = new Integer(123);        
               
        System.out.println("i1 == i2 = "+(i1 == i2));
        System.out.println("i1.equals(i2) = "+(i1.equals(i2)));
        
        System.out.println();
        System.out.println("i3 == i4 = "+(i3 == i4));
        System.out.println("i3.equals(i4) = "+(i3.equals(i4)));
        
        System.out.println();
        System.out.println("i2 == i4 = "+(i2 == i4));
        System.out.println("i2.equals(i4) = "+(i2.equals(i4)));
        
        System.out.println();
        System.out.println("i == i2 = "+(i == i2));
        System.out.println("i1.equals(i) = "+(i1.equals(i)));

        
        System.out.println();
        System.out.println("i == i4 = "+(i == i4));
        System.out.println("i4.equals(i) = "+(i4.equals(i)));

        ------------------------------ 
       i1 == i2 = true
      i1.equals(i2) = true

      i3 == i4 = false
      i3.equals(i4) = true

      i2 == i4 = false
      i2.equals(i4) = true

      i == i2 = true
      i1.equals(i) = true

      i == i4 = true
      i4.equals(i) = true


三、其他类怎么使用equals==
API里的类大部分都重写了equals方法,没有重写的一般是自己写的类,
如果是你自己定义的一个类,比较自定义类用equals==是一样的,都是比较句柄地址,
因为自定义的类是继承于object,而object中的equals就是用==来实现的,你可以看源码。 

四、javaequalshashCode之间什么关系
只是为了维护 hashCode 方法的常规协定,才要求用equals比较的两个对象的hashCode相同.
equals()hashCode()都来自java.lang.Object.你当然可以重写.

比如a.equals(b).仅当a的内存地址相等时,才返回true.当然如String等类已经对这个方法进行了重写,比较的就不再是内存地址了.
hashCode()的值也是与内存地址相关的.所以仅当内存地址相等时,hashCode才相等.

同样很多类也重写了这个方法,还是以String为例:
public int hashCode() {
int h = hash;
if (h == 0) {
      int off = offset;
      char val[] = value;
      int len = count;

      for (int i = 0; i < len; i++) {
         h = 31*h + val[off++];
      }
      hash = h;
   }
   return h;
}
就不在与内存地址相关了.这样做是为了保证用equals比较返回为true的两个对象,他们的hashCode是相同的.

所以一般重写equals的时候都会重写hashCode().
当然,这个相当于一个约定,一个协议.你不这么做并不会错

五、hashCode
在一般的应用中你不需要了解hashcode的用法,但当你用到hashmaphashset等集合类时要注意下hashcode

你想通过一个objectkey来拿hashmapvaluehashmap的工作方法是,
通过你传入的objecthashcode在内存中找地址,
当找到这个地址后再通过equals方法来比较这个地址中的内容是否和你原来放进去的一样,一样就取出value。 

所以这里要匹配2部分,hashcodeequals 
但假如说你new一个object作为key去拿value是永远得不到结果的,
因为每次new一个object,这个objecthashcode是永远不同的,所以我们要重写hashcode
你可以令你的hashcodeobject中的一个恒量,这样永远可以通过你的objecthashcode来找到key的地址,
然后你要重写你的equals方法,使内存中的内容也相等。。。


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑会员系统账号密码忘记了怎么办 推广渠道客户要求免费铺货怎么办 代理机构做的网站找不到人了怎么办 瓷砖买的和描述的不一样怎么办 网上买东西地址的省份写错了怎么办 驾校把预留号码注册错了怎么办 太害羞了不敢进店买东西怎么办 收件箱邮箱邮件满了但不想删怎么办 模拟人生畅玩版任务时间过了怎么办 快递放柜子里长时间不拿怎么办 古筝的筝码序号错了怎么办? 极限竞速3地平线爆内存怎么办 车载导航安卓系统禁止装软件怎么办 在微信上买东西买到假货怎么办 想从新西兰寄红酒到家运费怎么办 新买的裤子掉色把内裤染色了怎么办 白衣服变脏变黄怎么办用英文怎么说 经常宅在家里不爱出去玩怎么办 在家里呆不住老想着往外跑怎么办 新商盟网上订烟登录密码忘了怎么办 在拼多多购物质量有问题怎么办 美图手机总弹出一键加速广告怎么办 手机看小说总是喜欢弹出广告怎么办 美团外卖商家注册门头不合格怎么办 手机一打网页就自动弹出广告怎么办 美团预定的宾馆不可取消怎么办 公积金注册时的号码忘了怎么办 苹果7基带坏了修不好怎么办 苹果手机玩终结者2卡怎么办 支付宝转账转到邮箱忘记邮箱怎么办 朋友转账到我的邮箱支付宝怎么办 苹果账号密码和手机号码忘了怎么办 网上购物付款后商家不发货怎么办 夏商国际商城买到假货怎么办 重庆时时彩突然冻结账户资金怎么办 微信安全中心打不开是白色的怎么办 在淘宝买东西说好返现不给返怎么办 联通斐讯路由器返现被骗了怎么办 消费分期后退款分期账单还在怎么办 新房装修物业电梯用不了费用怎么办 在京东拼购没有拼成已付款的怎么办