关于equals()和==操作的一点理解

转载 2006年06月13日 15:18:00

经常会碰到一些==跟equals()方法的误用的例子,有时候自己也说不准就弄混了,特地查了些资料写个小小的总结;
首先大致声明一下默认的情况Object的==操作跟equals()是等效的;有些同志会说我错了,会说==操作是比较是否同
一对象的,equals()是比较两个对象内容是否相等的;这样的说法可以说对了一小半,错了一大半;
首先我们来看下Object对象的equals()方法是怎么实现的:
    public boolean equals(Object obj) {
    return (this == obj);
    }
 如何?这里已经很明显的告诉大家Object的==操作跟equals()是等效的吧.那有朋友就会问那怎么实现让equals()跟==操作不一样呢?
 怎么让equals()方法比较两个对象的内容呢?
 答案就是重写equals()方法;下面需要提到重写equals()方法要注意的几点规范:
 自反reflexive:    x.equals(x)  
 对称symmetric:    x.equals(y)=>y.equals(x)
 传递transitive:    x.equals(y),<code>y.equals(z) =>x.equals(z)
 稳定consistent:    x.equals(y) 每次调用的时候总是确定的返回true or false
 非空        x.equals(null) return false
 从属于==操作    x==y=> x.equals(y) return true

 还有非常重要的一点:改写equals()方法后,必须也要改写hashCode()方法; x.equals(y) => x.hashCode()==y.hashCode();
 上面解释了一堆关于重写equals()方法的原则,现在我们就倒过头来看看一些已经重写了equals()方法的具体的例子;首先拿String类型来考察
 //*************override equals()****************************
 public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
    }
//*************override hashCode()****************************
    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;
    }
    String类型通过重写了equals(),hashCode()方法实现了String对象的内容比较;基本类型的对象型比如Integer,Long,Float等类型都
    实现了自己的equals()方法;正因为基本类型都实现了对象的内容比较,所以经常给我们一种想当然的equals()是比较对象内容的错误观点.
    如果我们自己写的类要实现内容比较我们就需要自己重写equals()跟hashCode()方法,关于hashCode()的重写建议参考下String的处理方式,
    要尽量避免内容不相等的对象产生相同的hashCode()的错误,否则就会在hashTable中碰到散列值重复的问题,这个按下不表.

    最后额外的讲一下String的==的问题.经常碰到别人问String str="abc";String str2=new String("abc") String str3="abc"中有几个对象的无聊问题.
    这里我给出我自己的解释共str,str2,str3,"abc", new String("abc")五个对象.其中str,str2,str3是reference对象存于JVM的STACK中,"abc"是一个内存对象容纳
    了"abc"这个数据,存在于JVM的String池中(str,str3指向的"abc"是同一内存区--String池中的"abc"),new String("abc")是一个内存对象容纳了"abc"这个数据,存在
    于JVM的Heap 堆中;
    按照上面的解释我们可以明确知道str != str2,因为他们在内存中是两个对象(一个在STRING池中一个在HEAP堆中), str == str3因为他们指向的是String池中的同一对象;
    我们通过str="abc";str3="abc"实例化时,JVM会检查String池中是否已经存在"abc"对象,如果有那么就把引用指向已经存在的"abc";否则就在String池中新建立一个.
    我们通过str2=new String("abc")实例化时,首先这里分配的内存跟STRING池是没有任何关系的,无论HEAP堆和STRING池中有无"abc" JVM都会在HEAP堆里新建立一个
    "abc"对象;

 

 

检查对象是否相等
关系运算符==和!=也适用于所有对象,但它们的含义通常会使初涉Java领域的人找不到北。下面是一个例子:


  Equivalence {
     main(String[] args) {
    Integer n1 =  Integer(47);
    Integer n2 =  Integer(47);
    System.out.println(n1 == n2);
    System.out.println(n1 != n2);
  }
} 


其中,表达式System.out.println(n1 == n2)可打印出内部的布尔比较结果。一般人都会认为输出结果肯定先是true,再是false,因为两个Integer对象都是相同的。但尽管对象的内容相同,句柄却是不同的,而==和!=比较的正好就是对象句柄。所以输出结果实际上先是false,再是true。这自然会使第一次接触的人感到惊奇。
若想对比两个对象的实际内容是否相同,又该如何操作呢?此时,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“主类型”,那些类型直接使用==和!=即可。下面举例说明如何使用:


  EqualsMethod {
     main(String[] args) {
    Integer n1 =  Integer(47);
    Integer n2 =  Integer(47);
    System.out.println(n1.equals(n2));
  }
} 


正如我们预计的那样,此时得到的结果是true。但事情并未到此结束!假设您创建了自己的类,就象下面这样:


 Value {
   i;
}

  EqualsMethod2 {
     main(String[] args) {
    Value v1 =  Value();
    Value v2 =  Value();
    v1.i = v2.i = 100;
    System.out.println(v1.equals(v2));
  }
} 


此时的结果又变回了false!这是由于equals()的默认行为是比较句柄。所以除非在自己的新类中改变了equals(),否则不可能表现出我们希望的行为。不幸的是,要到第7章才会学习如何改变行为。但要注意equals()的这种行为方式同时或许能够避免一些“灾难”性的事件。
大多数Java类库都实现了equals(),所以它实际比较的是对象的内容,而非它们的句柄。

个人对hashCode与equals的区别与联系简单理解

一.首先equals()和hashcode()这两个方法都是从object类中继承过来的。  equals()方法在object类中定义如下: public boolean equals(Obje...
  • xdf0101
  • xdf0101
  • 2015年10月29日 14:56
  • 962

对equals和==的一点理解

概述:         简单的来说,equals是比较内容,==是比较地址值 详细:        内存可以分为堆内存和栈内存,简单的理解一般栈中主要存放一些基本类型的变量(,int, short, ...
  • weiyanjie100
  • weiyanjie100
  • 2014年08月12日 10:06
  • 254

【初学者常见问题】深入理解“==”和equals()

首先感谢老大在这一方面对我的指引。http://v.youku.com/v_show/id_XNjAzNTczMTI4.html 我将把我对于"=="和equals()体会和实例一起结合让菜鸟们能够深...
  • yangliding2011
  • yangliding2011
  • 2013年11月25日 14:50
  • 1038

Java学习从菜鸟变大鸟之一 hashCode()和equals()的本质区别和联系

equals()是判读两个Set是否相等[前提是equals()在类中被覆盖]。==决定引用值是否指向同一对象。 1、当向集合set中增加对象时,首先计算要增加对象的hashCode码,根据该值来得到...
  • lishehe
  • lishehe
  • 2014年01月28日 11:43
  • 5602

java-equals和==的比较规则和equals的重写

1、java中equals和==的区别 值类型是存储在内存中的堆栈(简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。 2、==操作比较的是两个变量的值是否相等,对...
  • defineshan
  • defineshan
  • 2016年08月22日 15:12
  • 750

Java中"=="和equals方法在字符串比较中的不同

昨天写代码的时候,遇到了比较两个字符串的值是否相同的情况,然后发现使用"=="和equals会得到不同的结果。其实我的目的是比较两个字符串的序列是否相同,这个时候应该使用equals方法的。大家在比较...
  • Life_0_1
  • Life_0_1
  • 2015年09月13日 10:53
  • 1790

Java 中 Equals和==的区别

在谈论equals和==的区别前,我们先简单介绍一下JVM中内存分配的问题。 在JVM中 内存分为栈内存和堆内存。二者有什么区别呢? 当我们创建一个对象(new Object)时,就会调用它的构造函数...
  • tcytcy123
  • tcytcy123
  • 2016年03月09日 16:19
  • 16104

关于equals 和 == 的理解

中软国际电子政务部Jeff Chi总结,转载请说明出处。 概述:        A.==可用于基本类型和引用类型:当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象是否相同。 ...
  • xiaohu26
  • xiaohu26
  • 2014年12月25日 21:12
  • 133

如何正确使用equals方法?

equals方法的覆盖看起来很简单,但是许多的覆盖方式都是错误的,将导致非常严重的后果,本文旨在介绍equals方法的使用规范,以规避错误的使用。...
  • zhanglong_daniel
  • zhanglong_daniel
  • 2015年12月27日 13:19
  • 2854

String比较为什么要用equals?用==的问题

很简单的问题,记录一下 下面的程序很简单吧?你能保证你说的结论都是正确的吗?运行验证下你的猜测。 public class T{ public static void main(String[] a...
  • look_dev
  • look_dev
  • 2016年10月22日 17:31
  • 564
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于equals()和==操作的一点理解
举报原因:
原因补充:

(最多只允许输入30个字)