为啥java 里要判断两个对象是不是相等呢?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥java 里要判断两个对象是不是相等呢?相关的知识,希望对你有一定的参考价值。

我是新手,现在学习到比较对象了。在网上找了找,都是教怎么用equal 方法比较对象相等的,我不明白的是为什么继承里要比较对象相等呢?
有一个父类,一个子类
当子类继承父类的时候,要放一个equal 方法比较对象是否相等
我的问题是:
1,为什么要比较对象相等?
2. 比较哪两个对象相等?父类子类里所有相同的对象么?还是子类里重写了哪个对象,就比较哪个对象在父类的相等?

你是不是想说为什么要重写equals方法?在我回答你问题之前,我想说:一个标准的实体类的4大基本规则:1.封装(属性私有化,分别提供对应的get与set方法等),2、提供无参构造 ,3、重写:toString(),equals(),hashCode()这3个方法,4、实现java.io.Serializable接口!

这是你就正好要问为什么要重写这3个方法,先说equals,重写它就是为了以后比较对象是否相等,比如你问题中的假如父类是person,子类是student,那么当我们new了几个student后,在程序中怎么去判断这几个 student实例是否是同一个学生呢?别告诉我用“=”去判断!这时如果我们的student重写了equals(比如你按照学号来比较),那么你就可以用S1.equals(S2)来比较了。至于hashCode,那是因为假如我们存取数据时 是存放在键值对中时(比如Map),这时候光靠equals效率不高,这时候用对象的哈希码(即hashCode方法得到的)来查找和比较更快,所以一般重写equals方法必须重写hashCode方法,因为java规定相等的对象必须有相等的哈希码!最后重写toString方法会让你打印和输出变得更顺利 等等。。。。。。高级QQ群:143551456诚邀爱交流的java初学者
参考技术A 这是面向对象的特性
由于java‘是纯面向对象语言,所以对对象的管理都是用自动分配的HashCode进行管理,这样的话用普通的“==”自然就不能解决问题。
试想一下,两个不同HashCode的String类型,拥有相同value的变量他们能是相等的么?
从对象的角度而言,肯定是不相等的。因为他们从直接寻址的角度而言,根本就是存储在不同地址的两个东西,但是他们在偏移地址上存储的分量value是相同的,从某种程度上来说有证明这两个String变量其实描述的是同一个东西。
如何让开发人员区分这两个情况,java想了一个比较好的方法
它用==来判断对象的HashCode相同的情况,同时提供了一个可重写的方法equals让程序员自定义判断两个对象实际相等的条件。
正如:
String s1 = new String("1");
String s2 = new String("1");
String s3 = s1;
System.out.println(s1==s2);
System.out.println(s1.equals(s2));
System.out.println(s1==s3);
System.out.println(s1.equals(s3));

结果是什么呢?自己想啦
参考技术B 首先你弄错了,比较对象没有为什麼。equal只适合字符串比对
对象类型比较默认是比 内存地址(如:0x2652ds)
对象比较要实现Comparable的方法,比较对象的属性,
具体的说不清楚。
找个人指导下你吧。
参考技术C 1、比较对象相等在条件判断时用到。
2、比较的是你定义的对象,如果是在子类中定义的话,就是重写的equals方法。
参考技术D 不晓得

Java 判断两个对象是否相等

一、使用 == 与 equals

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

  • 情况1:类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
  • 情况2:类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true (即,认为这两个对象相等)。

举个例子:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 为一个引用
        String b = new String("ab"); // b为另一个引用,对象的内容一样
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 从常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一对象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

说明:

  • String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
  • 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。

二、使用 hashCode 与 equals

面试官可能会问你:“你重写过 hashcode 和 equals 么,为什么重写equals时必须重写hashCode方法?”

hashCode()介绍

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。另外需要注意的是: Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法通常用来将对象的 内存地址 转换为整数之后返回。

    /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

为什么要有hashCode

我们以“HashSet如何检查重复”为例子来说明为什么要有hashCode:

当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。(摘自我的Java启蒙书《Head fist java》第二版)。这样我们就大大减少了equals的次数,相应就大大提高了执行速度。

hashCode()与equals()的相关规定

  1. 如果两个对象相等,则hashcode一定也是相同的
  2. 两个对象相等,对两个对象分别调用equals方法都返回true
  3. 两个对象有相同的hashcode值,它们也不一定是相等的
  4. 因此,equals方法被覆盖过,则hashCode方法也必须被覆盖
  5. hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

为什么两个对象有相同的hashcode值,它们也不一定是相等的?

以下内容摘自《Head Fisrt Java》:

因为hashCode() 所使用的杂凑算法也许刚好会让多个对象传回相同的杂凑值。越糟糕的杂凑算法越容易碰撞,但这也与数据值域分布的特性有关(所谓碰撞也就是指的是不同的对象得到相同的 hashCode)。我们刚刚也提到了 HashSet,如果 HashSet 在对比的时候,同样的 hashcode 有多个对象,它会使用 equals() 来判断是否真的相同。也就是说 hashcode 只是用来缩小查找成本。

以上是关于为啥java 里要判断两个对象是不是相等呢?的主要内容,如果未能解决你的问题,请参考以下文章

如何判断两个对象的值是不是相等java

Java 复习1

Java 判断两个对象是否相等

Java中怎么比较两个字符串是不是相等?

c# 比较两个对象的值是不是相等

JAVA比较两个字符串是不是相等用啥