zoukankan      html  css  js  c++  java
  • 夯实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()方法。

  • 相关阅读:
    iOS推送通知
    KVO内部实现原理
    沙盒目录结构
    UITableView的常用属性和代理方法
    优秀文章的链接
    c++面试题
    递归练习
    c#连接mysql环境配置
    mysql命令详解
    十进制转二进制
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/11216641.html
Copyright © 2011-2022 走看看