zoukankan      html  css  js  c++  java
  • Java基础(007):关系运算符==和equals的区别

    • ==(或者 != ) : 关系运算符,既可以用于基本类型的数值相等性比较,也可以用于对象引用之间的关系判断,此时是对象引用等价性比较,即是否都是同一个对象的引用(引用地址是否相同)[1]。从另一个角度看,本质上也是数值比较,只是这里的数值是引用地址/内存地址而已。
    • equals : 是一个实例方法,存在于Java的顶层父类Object中,因此所有类都会继承,而且只能作用于对象间的比较,而基本类型不属于引用类型,所以equals并不适用于基本类型间的判断(可以是 包装器类型.equals(原始数据类型),原始数据类型会自动装箱)。equals方法也是用于两个对象的相等性判断,不过这种等价性判断需要根据是否重写equals方法来具体区分。

      Object.equals(Object obj)方法具体如下:

    public boolean equals(Object obj) {
        return (this == obj);
    }

      可以看到,原始的equals方法实质上就是用==做判断,也即是引用地址的等价性判断。实际上很多时候会在子类中重写equals方法,按需实现等价性判断。因此equals方法的等价性判断主要有以下2种场景:

    • 场景1:子类使用默认的 Object.equals(Object obj) 而不重写,此时可以看作等价于==,即对象引用地址的等价性判断。
    • 场景2:按需重写equals方法,此时一般用于对象内容等价性的判断,这种场景下,在指定的内容一致时我们可以认为对象是相等/等价的,Java API 中比较典型的应用有以下几种:
      • 集合框架实现类中的元素等价性判断
      • String 类
      • 基本类型的包装类

      另外需要注意的是:对于==返回true的对象判断,equals肯定也是返回true,因为引用地址一样,都是指向同一个对象;反过来equals返回true不一定意味着是指向同一个对象,还很可能只是对象的内容一样而已。例如名字为 “张三”的可能会有很多个人,你认识的张三可能也是别人认识的张三(==equals都返回true),也可能不是别人认识的张三(==返回falseequals返回true),但名字确实都是张三。

      综合案例(github传送门)如下:

    public class RelationalOperatorsVsEquals {
        public static void main(String[] args) {
            Integer int1 = -128;
            Integer int2 = -128;
            // 实际上 int1 和 int2 都是 Integer 缓冲池[-128,127] 中的同一个缓存对象
            System.out.println("int1 == int2 : " + (int1 == int2));
            System.out.println("int1.equals(int2) : " + (int1.equals(int2)));
            
            Integer int3 = 128;
            Integer int4 = 128;
            // 此时的 int3 和 int4 指向的2个完全不同的对象,但是内部数值其实是等价的
            System.out.println("int3 == int4 : " + (int3 == int4));
            System.out.println("int3.equals(int4) : " + (int3.equals(int4)));
            
            String str1 = "ZhangSan";
            String str2 = "ZhangSan";
            // 实际上 str1 和 str2 都是指向常量池上的 "ZhangSan"
            System.out.println("str1 == str2 : " + (str1 == str2));
            System.out.println("str1.equals(str2) : " + (str1.equals(str2)));
            
            String str3 = new String("ZhangSan");
            String str4 = new String("ZhangSan");
            // 此时的 str3 和 str4 指向的不同的堆对象 "ZhangSan"
            System.out.println("str3 == str4 : " + (str3 == str4));
            System.out.println("str3.equals(str4) : " + (str3.equals(str4)));
            System.out.println("str1 == str3 : " + (str1 == str3));
            System.out.println("str1.equals(str3) : " + (str1.equals(str3)));
        }
    }
    
    // ......
    // result
    int1 == int2 : true
    int1.equals(int2) : true
    int3 == int4 : false
    int3.equals(int4) : true
    str1 == str2 : true
    str1.equals(str2) : true
    str3 == str4 : false
    str3.equals(str4) : true
    str1 == str3 : false
    str1.equals(str3) : true

    注:更多关于equals的说明,建议先参考Object.equals(Object obj)详细的API文档说明(源码javadoc注释)。后续笔者将在集合框架的相关说明中进一步讲解(和 hashCode 方法等)。

    注:关于String、包装类对equals方法重写的具体实现,同样还是建议直接参考相关的JDK API源码。

    参考:

     

  • 相关阅读:
    Oracle expdp 多表导出处理
    字符串
    Java设计模式
    多线程
    Java面向对象练习
    Java面向对象基础
    Java基础算法
    Java常识
    DOS基础命令(1)
    Java基础练习
  • 原文地址:https://www.cnblogs.com/wpbxin/p/14383293.html
Copyright © 2011-2022 走看看