Hey, Nice to meet You. 

必有过人之节.人情有所不能忍者,匹夫见辱,拔剑而起,挺身而斗,此不足为勇也,天下有大勇者,猝然临之而不惊,无故加之而不怒.此其所挟持者甚大,而其志甚远也.          ☆☆☆所谓豪杰之士,

夯实Java基础(五)----==与equals()

1、前言

我们在学习Java的时候,看到==、equals()就认为比较简单,随便看了一眼就过了,其实你并没有深入去了解二者的区别。这个问题在面试的时候出现的频率比较高,而且据统计有85%的人理直气壮的答错。所以理解==与equals()的区别很有必要。

2、==运算符

==可以使用在基本数据类型变量和引用数据类型变量中。

1、如果比较的是基本数据类型变量:比较两个变量的数值是否相等(数据类型不一定要相等,只看值,因为会类型自动提升!);

2、如果比较的是引用数据类型变量:比较两个对象的地址值是否相等。

下面看一下案例:

public class Test {
    public static void main(String[] args) {
        int a=10;
        int b=10;
        double c=10.00;
        System.out.println(a==b);//true
        System.out.println(a==c);//true

        String str1="123";
        String str2="123";
        System.out.println(str1==str2);//true

        String str3=new String("123");
        String str4=new String("123");
        System.out.println(str3==str4);//false
    }
}

结果为:true、true、true、false。前面两个为true的结果非常容易理解,但是第三个为true,第四个为false,而它们都是String引用类型,为什么不一样呢?

分析原因:

对于8种基本数据类型(byte,short,char,int,float,double,long,boolean)的值而言,它们都是存储在常量池中,而str1、str2的字符串 "123" 也同样在常量池中,而一个常量只会对应一个地址,因此不管是再多的数据都只会存储一个地址,所以所有他们的引用都是指向的同一块地址,因此基本数据类型和String常量是可以直接通过==来直接比较的。

而str3、str4分别在堆内存中创建的两个对象,地址值自然就不相同了。

3、equals()方法

equals()是一个方法,不是数据类型,所以他只适用于引用数据类型。

该方法主要用于比较两个对象的内容是否相等。其实这样的说法是不准确的。首先我们来看看在Object类中定义的equals方法:

可以看到,在Object类型的equals方法是直接通过==来比较的,和==是没有任何区别的。

那么为什么又要说equlas和==的区别呢?是因为所有的类都直接或间接地继承自java.lang.Object类,因此我们可以通过重写equals方法来实现我们自己想要的比较方法。

我们创建一个Person类来测试,先不重写父类的equals()方法:

public class Test {
    public static void main(String[] args) {
        Person person1=new Person("菜徐坤",21);
        Person person2=new Person("菜徐坤",21);
        System.out.println(person1.equals(person2));
    }
}

class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

毫无疑问,输出的结果肯定是false,因为没有重写父类的equals()方法,从而调用了父类的,而父类的equals()方法是用==判断的。

然后我们重写父类的equals()方法:

public class Test {
    public static void main(String[] args) {
        Person person1=new Person("菜徐坤",21);
        Person person2=new Person("菜徐坤",21);
        System.out.println(person1.equals(person2));
    }
}

class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }
}

重写之后输出就是true了,因为比较的对象的内容。

实际上,像String、Date、Math、File、包装类等大部分类都重写了Object的equals()方法。重写以后,就不是比较两个对象的地址值是否相同了,而是比较两个对象里面的内容是否相等。

下面我们来看一下String类重写的equals()方法:

* @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    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;
    }

可以看到重写的方法内用char[] 数组进行一个一个的比较,并不是用==进行比较,。

我们在重写equals()方法时必须要遵循如下几个规则:

  1. 自反性:x.equals(x)必须返回是true。
  2. 对称性:如果x.equals(y),返回时true,那么y.equals(x)也必定返回为true。
  3. 传递性:如果x.equals(y)返回的true,而且y.equals(z)返回是true,那么z.equals(x)返回的也是true。
  4. 一致性:如果x.equals(y)返回是true,只要x和y的内容一直不变,不管重复x.equals(y)多少次,返回都是true
  5. 任何情况下,x.equals(null),永远返回是false,x.equals(与x是不同类型的对象),也永远返回是false。

对于上面几个规则,我们在使用的过程中最好遵守,避免出现意想不到的错误。

4、小结

1、==比较的数值是否相等和对象地址是否相等。

2、equals()方法比较的对象内容是否相等(前提是重写了父类的方法)。

3、一般除了自定义的类除外,大部分能够使用的类都重写了equals()方法。

posted @ 2019-07-20 14:56  唐浩荣  阅读(345)  评论(0编辑  收藏  举报