zoukankan      html  css  js  c++  java
  • Java中==与equals的区别

    要想理解它们俩之间区别,首先要了解一下它们的定义。

    • ==比较的是变量(栈)中存放的对象(堆)的内存地址是否相同,即是否指向同一个对象。比较是真正意义上的指针操作。
    • equals比较的是两个对象的内容是否相同,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。

    也就是说==是一个指针操作,用来比较数值相等,而equals则是一个方法,在Object类中equals方法中使用其实就是==,如果子类不重写equals方法,两者则并没有什么不同。


    我们看Object类中equals方法如下:

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

    对于==和equals我们需要分别从两种数据类型,基本数据类型和引用数据类型进行对比。

    先说==,对于基本数据类型,也就是我们常说的int、char、long、short、boolean、double、float、byte这八种,他们之间的比较需要使用==,因为他们比较的是值。那它们可以使用equals方法嘛?不可以的,因为它们是基本数据类型,不是继承于Object类,自然也就没有equals方法之说。对于引用类型,==比较是变量中存放的对象的内存地址是否相同,所以除非是同一个new出来的对象,它们通过==比较出来的结果是true,因为每new一次都会开辟一块新的内存空间。

    在说说equals方法,刚才说了对于基本数据类型是没有equals方法之说,对于引用数据类型,如果它没有重写equals方法,那还是沿用Object类中的equals方法,即实际通过==来进行比较,比较是变量中存放的对象内存地址是否相同。

    ==和equals方法之间的区别基本就是这些,下面说说一些特殊类堆Object中的equals方法进行重写的案例。

    首先是String类,我们知道String是一种特殊的引用数据类型,比如以下代码,

        String str1="Hello World";
        String str2="Hello World";

    那么如果比较str1==str2得到是true,因为字符串的值是final的不可改变的,相同的字符串在内存中只会存一份,所以str1和str2指向的内存地址是一样的。

    如果写成这种形式呢?

         String str1=new String("Hello World");
         String str2=new String("Hello World");    

    此时再比较str1==str2得到是false,因为使用new关键字它们俩各自强行开辟了一块内存空间,这样str1和str2指向的内存地址是不一样。

    对于equals方法,在String类中对equals方法进行了重写,源代码如下:

    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            if (anObject instanceof String) {
                String anotherString = (String)anObject;
                int n = value.length;
                if (n == anotherString.value.length) {
                    char v1[] = value;
                    char v2[] = anotherString.value;
                    int i = 0;
                    while (n-- != 0) {
                        if (v1[i] != v2[i])
                            return false;
                        i++;
                    }
                    return true;
                }
            }
            return false;
        }

    在String类equals方法中首先是比较对象是否一样,如果一样则返回true,如果不一样再对比每一个字符是否一样,如果都一样,也同样返回true。

    再看看Integer类,同样Integer类也对equals方法进行了重写:

    public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }

    实际比较的还是两个基本数据类型(int)的值是否相等。

    还有个细节的东西可以说明下,我们看下面代码的输出结果:

            String str1="Hello";
            String str2="Hello";
            
            String str3=new String("Hello");
            String str4=new String("Hello");
            
            System.out.println("str1==str2?"+(str1==str2));
            System.out.println("str1==str3?"+(str1==str3));
            System.out.println("str3==str4?"+(str1==str2));
            
            int a=1;
            int b=1;
            
            Integer i1=new Integer(1);
            Integer i2=new Integer(1);
            
            System.out.println("a==b?"+(a==b));
            System.out.println("a==i2?"+(a==i2));
            System.out.println("i1==i2?"+(a==b));

    结果:

    str1==str2?true
    str1==str3?false
    str3==str4?true
    a==b?true
    a==i2?true
    i1==i2?true

    对于字符串的对比可能不会有太大的意外,原因我们上面也都讲到了,只是对于“a==i2”这个为什么返回的也是true呢?难道变量a和i2存放的内存地址是一样的吗?这显然不正确,毕竟a是基本数据类型,存放的地址是栈中的地址,而i2是引用数据类型,存放的地址应当指向对中的地址。这是因为当Integer与int进行==比较时,Integer就会拆箱成一个int类型,所以还是相当于两个int类型进行比较,这里的Integer,不管是直接赋值,还是new创建的对象,只要跟int比较就会拆箱为int类型,所以就是相等的。其实所有的包装类在和其基本数据类型==比较时都会自动拆箱。

    通过比较==和equals方法,我们发现,越是简单的东西,可能越不容易理解,越需要时间和精力去关注。

  • 相关阅读:
    打造自己的性能测试类
    网站配置之最佳实践
    C#控制台窗口居中显示(转)
    将PDM文件导出成CHM帮助文件
    分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限
    Oracle 给已创建的表增加自增长列
    托管调试助手“NonComVisibleBaseClass”检测到问题
    翻页效果
    Excel表格转Json数据结构
    关于2D渲染的一些小想法
  • 原文地址:https://www.cnblogs.com/Jerryoned/p/13252110.html
Copyright © 2011-2022 走看看