Java中==与equals的区别

Posted Jerryoned

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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方法,我们发现,越是简单的东西,可能越不容易理解,越需要时间和精力去关注。

 

以上是关于Java中==与equals的区别的主要内容,如果未能解决你的问题,请参考以下文章

Java中“==”与equals方法的区别

Java中==与equals的区别

java中equals和equalsignorecase的区别

java中equals和equalsignorecase的区别

java中equals与==号的区别

Java中==与equals()的区别