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

一、前言

咱们在学习Java的时候,看到==、equals()就认为比较简单,随便看了一眼就过了,其实你并无深刻去了解两者的区别。这个问题在面试的时候出现的频率比较高,并且据统计有85%的人义正词严的答错。因此理解==与equals()的区别颇有必要。java

二、==运算符

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

一、若是比较的是基本数据类型变量:比较两个变量的数值是否相等(数据类型不必定要相等,只看值,由于会类型自动提高!);数组

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

下面看一下案例:学习

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引用类型,为何不同呢?测试

分析缘由:this

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

而str三、str4分别在堆内存中建立的两个对象,地址值天然就不相同了。code

三、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。

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

四、小结

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

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

三、通常除了自定义的类除外,大部分可以使用的类都重写了equals()方法。

相关文章
相关标签/搜索