一、equals()和==
1、equals()
java中所有的类都直接或间接继承Object这一基类,而equals()是Object类中的方法,所以equals()是每个类都拥有的方法,至于eqauls()方法的作用则需要看它的具体实现了。下面是Object中equals()方法的实现:

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

从中可以看出,Object中的equals()方法用于比较两个对象的引用是否相等,是否指向的是同一个对象。
2、==
对于基本数据类型来说,==用于判断的两个变量的值是否相等。而对于引用类型来说,比较的是两个对象的引用是否指向同一个对象。

因此可以总结出,如果继承Object的类不对equals()方法进行重写的话,equals()的作用与==相同。但不同的是equals()不能用于基本数据类型,而==可以。

二、String中的equals()方法
String源码中的equals()是被重写过的,可以直接用于比较两个String中的对象的值是否相等,当然如果比较的两个String对象引用指向的是同一对象,结果也为true。下面来看看String中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.value;
                while(n--!=0){
                    if(v1[i++]!=v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }

举个例子:

public class Test5{
        public static void main(String[] args) 
        {
            String str1=new String("abc");
            String str2=new String("abc");
            System.out.println(str1.equals(str2));
            System.out.println(str1==str2);
        }
}

运行结果如下:

java中eq Java中equals重写_Test

也许有人,在写下面两句语句:

String str1=new String("abc");
    String str2=new String("abc");

时,这般写:

String str1="abc";
String str2="abc";

可能很多人觉得这两种方式没有什么不同,然而,结果是不尽相同的。

替换语句后的结果如下:

java中eq Java中equals重写_bc_02

这主要是因为String pool(字符串常量池)机制的原因,这个我会在之后的博客解释。

二、重写equals()方法的模式
如果你想实现这样的效果:如果同一个类new的两个对象的成员属性相等的话,equals()方法结果返回true。那么我们可以根据上面String的equals()方法的模式重写equals()方法,一般模式如下:

public boolean equals(Object obj){
    if(obj是否为所要判断的类的对象)
    {
        /*判断obj引用的类对象是否与激活该方法的类对象具有相同的值
        。如果值相同则返回true,否则返回false。*/
    }
    else
       return false;
}

示例:

public class Test {
    private int a;
    public String str;

    public Test(int a,String str){
        this.a=a;
        this.str=str;
    }

    public boolean equals(Object obj){
        if(obj instanceof Test){
            Test test=(Test)obj;
            return (test.a==a)&&(test.str.equals(str));
        }else{
            return false;
        }
    }
    public static void main(String[] args) 
    {
        Test t1=new Test(1,"abc");
        Test t2=new Test(1,"abc");
        System.out.println(t1.equals(t2));
    }
}

来看一下这个if语句:

if(obj instanceof Test){
        Test test=(Test)obj;
        return (test.a==a)&&(test.str.equals(str));
        }

这里,或许会有人疑惑:为什么需要下面这一句?

Test test=(Test)obj;

而不是直接

return (obj.a==a)&&(obj.str.equals(str));

个人认为具体的原因是:
在主方法调用equals()方法时,会执行如下语句的功能:

Object obj=t2;

也就是实参赋值于形参。在这个过程中,子类的对象引用转换为父类的对象引用,发生了面向对象语言中的“向上转型”。
而java的对象引用向上转型后,是不能调用子类独有的方法和属性的。所以我们必须将obj进行强制转换。

第二点会有人疑惑的点是:
语句return (test.a==a)&&(test.str.equals(str)); 直接访问了Test类的私有变量a和str。
为什么可以这样访问呢?
答案是:只要方法所属类与对象的类型是相同的类,那么该方法就能访问对象的私有实例变量。

抱歉,有点啰嗦!



参考文献:
《数据结构 Java语言描述 第3版》 –Michael Main