首页 > 编程语言 > 详细

Java == 和 equals() 区别.md

时间:2015-03-22 16:36:10      阅读:242      评论:0      收藏:0      [点我收藏+]

==

==可以用于基本类型和引用类型的比较,比较基本类型时,是比较其值是否相同;比较引用类型时,是比较其是否引用了同一对象(其实也是比较其值是否相同,这里的值是对象的地址)。例如:

int a = 1;
System.out.println(a == 1);             // true

String s1 = "hello";
String s2 = s1;
System.out.println(s1 == s2);           // true

String s3 = "hello";
String s4 = new String("hello");       
System.out.println(s1 == s3);           // true
System.out.println(s1 == s4);           // false

其中s1 == s3结果为true,这个与JVM工作机制有关,后面会解释。

equals()

equals()用于比较两个对象的内容是否相同,例如:

String s1 = "hello";
String s4 = new String("hello"); 
System.out.println(s1 == s4);           // false
System.out.println(s1.equals(s4));      // true

equals()是基类Object的一个方法,其默认实现如下(摘自java SDK源码),可见默认调用==来比较。

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

如果没有override该方法,那么就退化为和==相同的功效了。但是一般都会override该方法,用来比较两个对象内容是否相同,例如Stringequals()会比较字符串序列是否相同,所以,如果要比较对象内容是否相同用equals,对于自定义对象,根据需要override该方法。

字符串池

下面代码中,字符串s1 == s3true,表示他们都引用了相同对象,这与new String("hello")差异在哪里呢?

String s1 = "hello";
String s3 = "hello"; 
String s4 = new String("hello");       
System.out.println(s1 == s3);           // true
System.out.println(s1 == s4);           // false

JVM中有一个称为”字符串池”的共享区域,用来保存字符串常量,每当创建字符串常量时,会先查找字符串池,如果找到返回其引用,如果不存在则创建一个新的字符串,并添加到字符串池中。注意:该规则仅针对字符串常量,对于通过new创建的字符串没有该规则。

字符串常量,包括字面值(literal strings)和常量表达式(string-valued constant expressions),例如:

String s1 = "hello";                            // 字符串常量
String s2 = "h" + "e" + "l" + "l" + "o";        // 字符串常量
System.out.println(s1 == s2);           // true
System.out.println(s1.equals(s2));      // true

String s3 = "hello" + s1;                       // 非字符串常量

s1 = "hello"由于是字符串常量,创建时又不存在,所以创建时会被添加到字符串池中,当创建s2时,由于s2也是一个字符串常量(虽然是拼接而成,但每个组成部分都是常量,在编译时就可以确定,所以其也是字符串常量),其创建时会先查找字符串池,找到并返回引用,该引用与s1相同,所以s1 == s2比较为true,自然equals()比较也为true

可见定义多个相同的字符串常量值,其只占用一份内存空间,只会被创建一次,性能上好些。

java.lang.String中 equals() 的实现

最后一起看看java.lang.String类的equals()的源码,主要看下其实现原理和方法,方便我们为自定义类重写equals()方法时提供参考。

// java/lang/String.java
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;
}

首先判断引用是否相同,如果引用相同,那么内容必然相同,直接返回true。接下来判断比较对象是否是String类的一个实例,这样做是为了保证被比较对象类型一致(如果比较的两个对象是继承关系,这里也视作类型不同),类型一致后,比较字符串的长度,如果长度相同则比较字符串的每个字符,如果每个字符都相同返回true,对于其他情况都返回false

为自定义类重写 equals() 方法

通过前面的学习,对equals()有了一些了解,下面通过为自己的类重写equals()方法来巩固一下。代码如下:

class MyInteger {
    private int mValue;

    public MyInteger(int v) {
        mValue = v;
    }

    public int getValue() { return mValue; }

    public int hashCode() { return mValue; }

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

        if (obj instanceof MyInteger) {
            MyInteger i = (MyInteger)obj;
            if (mValue == i.getValue()) {
                return true;
            }
        }

        return false;
    }
}

public class Test {
    public static void main (String [] args) {
        MyInteger i1 = new MyInteger(100);
        MyInteger i2 = new MyInteger(100);
        System.out.println(i1 == i2);               // false
        System.out.println(i1.equals(i2));          // true
    }
}

MyInteger是一个很简单的类,其只包含一个int类型的成员变量,在equals()中,我仿照java.lang.String类,先判断引用是否相同,如果相同直接返回true,如果引用不相同,再判断被比较对象是否是MyInteger类型,如果是再比较成员变量mValue是否相同,如果相同返回true,其他情况返回false

也许你注意到了,我还定义了一个hashCode()成员函数,这是JDK中要求的,查看java.lang.Objectequals()方法说明,其中提到重写equals()方法时,一般也需要重写hashCode()(我感觉是必须啊,不然编译不过–!)。而且要保证如果两个对象使用equals()比较相同,则被比较的两个对象的hashCode()返回值也必须相同,反之亦然。

在自定义的MyInteger中由于只有一个成员变量,可以直接在hashCode()的实现中直接返回该成员变量,这样可以保证上面所说的要求。

Java == 和 equals() 区别.md

原文:http://blog.csdn.net/xiaohui_hubei/article/details/44538145

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!