美文网首页
Java中==和equals的使用区别

Java中==和equals的使用区别

作者: 文景大大 | 来源:发表于2019-05-10 11:07 被阅读0次

    在Java中“==”的含义需要看比较的是什么类型的数据。

    如果比较的都是基本类型的数据,那么“==”的含义就是比较它们之间的值是否相等:

    public static void main(String[] args) throws Exception {
    
            int a = 10;
            int b = 10;
            double c = 10.0;
            double d = 10.0;
    
            // print true
            System.out.println(a == b);
            // print true
            System.out.println(a == c);
            // print true
            System.out.println(c == d);
    
        }
    

    如果比较的都是引用数据类型,那么比较的是两者之间存放内容的地址是否是相等,而不是比较它们的内容,如何证明这一点呢?我们来看如下的例子:

        public static void main(String[] args) throws Exception {
    
            String s1 = "zhangsan";
            String s2 = "zhangsan";
            String s3 = new String("zhangsan");
            String s4 = new String("zhangsan");
            String s5 = s3;
    
            // print true
            System.out.println(s1 == s2);
            // print false
            System.out.println(s1 == s3);
            // print false
            System.out.println(s3 == s4);
            // print true
            System.out.println(s3 == s5);
    
        }
    

    s1和s2都是字符串常量值,它们被放置在栈内存中,相同内容只会保留一份,所以当比较它们的时候,都是指的同一份内容,即地址也是相同的,因此返回true;

    s3是新建了一个对象,存放在堆内存中,它和s1虽然内容相等,但是存放的地方不一样,地址当然也是不同的,因此它们比较的结果是返回false;

    s4是仿照s3重新建立了一个对象,在堆内存中,即使相同内容的对象也是两个不同的对象,所以它们地址是不同的,比较的结果是false;

    s5是赋值了s3对象所在的地址,那么此时s3和s5都是指向堆内存中相同的地址,因此它们比较的结果是返回true;

    知道了“==”的作用后,我们再来看看equals的作用。equals最早是在Object类中出现的,因此,可以理解为所有的类都是具有equals方法的,如下是Object中的相关源码:

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

    也就是说,默认情况下,任何对象之间使用equals方法进行比较,比较的是两者之间的地址是否相同,和“==”的作用一模一样:

    public class Fruit {
    
        private String name;
        private Integer weight;
    
        public Fruit(){}
    
        public Fruit(String name, Integer weight){
            this.name = name;
            this.weight = weight;
        }
    
        // setters and getters...
    
        public static void main(String[] args) throws Exception {
    
            Fruit apple1 = new Fruit("apple",13);
            Fruit apple2 = new Fruit("apple",13);
    
            // print false
            System.out.println(apple1.equals(apple2));
            // print false
            System.out.println(apple1 == apple2);
        }
    

    那么如何才能使用equals方法来比较两个对象之间的内容是否相等呢?这个其实在我们日常使用的String和Integer中已经实现了的。

    public static void main(String[] args) throws Exception {
    
            String s1 = new String("zhangsan");
            String s2 = new String("zhangsan");
            String s3 = new String("lisi");
    
            // print true
            System.out.println(s1.equals(s2));
            // print false
            System.out.println(s1 == s2);
            // print false
            System.out.println(s1.equals(s3));
    
            Integer t1 = new Integer(10);
            Integer t2 = new Integer(10);
            Integer t3 = new Integer(1);
    
            // print true
            System.out.println(t1.equals(t2));
            // print false
            System.out.println(t1 == t2);
            // print false
            System.out.println(t1.equals(t3));
        }
    

    为什么String和Integer就可以做到比较的是内容,而不是存放内容的地址呢?我们来看下它们的源码是怎么实现的:

        // 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;
        }
    
        // Integer源码中equals方法实现
        public boolean equals(Object obj) {
            if (obj instanceof Integer) {
                return value == ((Integer)obj).intValue();
            }
            return false;
        }
    

    如此,我们得出结论,想要通过equals方法来比较两个对象的内容是否相等,是需要重写从Object中继承而来的equals方法的,如果不重写,那么默认就是比较的两个对象的地址。

    我们在刚才的Fruit中增加equals的重写,这个使用IDE可以自动生成:

    public class Fruit {
    
        private String name;
        private Integer weight;
    
        public Fruit(){}
    
        public Fruit(String name, Integer weight){
            this.name = name;
            this.weight = weight;
        }
    
        @Override
        public boolean equals(Object o) {
            // 被比较对象等同自身则返回true
            if (this == o) return true;
            // 被比较对象等于null或者两个根本是不同的类型则返回false
            if (o == null || getClass() != o.getClass()) return false;
            // 将被比较对象强制转成相同的类型
            Fruit fruit = (Fruit) o;
            // 将对象中的各个属性依次进行比较,都相同的情况下才返回true
            return Objects.equals(name, fruit.name) &&
                    Objects.equals(weight, fruit.weight);
        }
    
        // setters and getters...
    
        public static void main(String[] args) throws Exception {
    
            Fruit apple1 = new Fruit("apple",13);
            Fruit apple2 = new Fruit("apple",13);
    
            // print true
            System.out.println(apple1.equals(apple2));
            // print false
            System.out.println(apple1 == apple2);
    
        }
    

    重写后的对象使用equals方法就比较的是两个对象的内容了。

    PS:
    如上重写的equals中,使用了Objects工具类的equals方法,两个比较的属性是否相等需要取决于属性自身是否重写自身的equals方法。如下是相关的源码:

        public static boolean equals(Object a, Object b) {
            return (a == b) || (a != null && a.equals(b));
        }
    

    相关文章

      网友评论

          本文标题:Java中==和equals的使用区别

          本文链接:https://www.haomeiwen.com/subject/hgsooqtx.html