首页 > 代码库 > 【Java基础】“equals” 和 “==”的理解

【Java基础】“equals” 和 “==”的理解

简述:
==: 用于基本类型和引用类型:当用于基本类型时候,是比较值是否相同;当用于引用类型的时候,是比较对象(内存地址)是否相同;
equals: java.lang包中的Object类有public boolean equals(Object obj) { return (this == obj) }方法,它比较两个对象是否相等;

故对于引用类型在一定程度上,"==" 和 "equals"的功能是一致的,都是比较对象(内存地址)是否相同;

 

1、JDK常用类的“==”和“equals()”的区别:

JDK中常用类String、基础类型的封装类型都重写了equals()方法,故才有下例的中的结果:

//String重写了Object的equals()方法,比较相同index的字符是否一致(基础类型char的比较"==")//同时也发现基础类型的封装类型,同样也重写了equals()方法,故平时使用时equals()给我们的印象是比较本身的值是否相同;//char[Character], byte[Byte], short[Short], int[Integer], long[Long], float[Float], double[Double], boolean[Boolean]String a = new String("s");String b = new String("s");System.out.println(a.equals(b));//print trueSystem.out.println(a == b);//print false

故在引用类型的比较上,个人感觉equals()方法是对“==”的补充,完成“==”做不到的功能(比较对象的内容是否相同)!

 

2、String类中“==”的细节:

对于引用类型,“==”比较对象(内存地址)是否相同,但是下例中的结果却并不完全遵循上述的描述:

String a = new String("s");String c = "s";String d = "s";System.out.println(c == d); //print trueSystem.out.println(c == a); //print false

其原因:在JVM内,存在字符串池,其中保存着很多 String对象,并且可以被共享使用。

其过程:如果要创建下一个字符串对象,JVM首先会到字符串池中寻找,是否存在对应的字符串对象,如果存在,则返回一个己存在对象的对象的引用给要创建的对象引用.

       如果不存在,才会创建一个新的对象,并返回一个新对象的对象引用给要创建的对象引用。故例子中 c == d返回值是true。

而对于 String a = new String("s"),共有“s”, a两个String对象,且a是不存放到字符串共享池中的,故例子中c == a返回值是false

上述的描述同样适用于Integer等基础类型的封装类;

 

3、普通类的“equals()”重写:

受到String类的启发,我们也可以来重写自定义类的equals()方法,如下例:

public class Equals {    private String name = "";    private int age = 0;    public Equals(String name, int age) {        this.name = name;        this.age = age;    }    @Override    public boolean equals(Object obj) {        if(this == obj){            return true;        }        if(obj instanceof Equals){            Equals equ = (Equals) obj;            return this.name.equals(equ.name) && this.age == equ.age;        }        return false;    }    @Override    public int hashCode() {        return 31 * this.name.hashCode() + ((Integer)this.age).hashCode();    }    public static void main(String[] args) {        Equals eq1 = new Equals("s", 3);        Equals eq2 = new Equals("s", 3);        System.out.println(eq1.equals(eq2));        System.out.println(eq1 == eq2);    }}

重写equals必须注意:
1. 自反性:对于任意的引用值x,x.equals(x)一定为true
2. 对称性:对于任意的引用值x 和 y,当x.equals(y)返回true,y.equals(x)也一定返回true
3. 传递性:对于任意的引用值x、y和 z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回 true
4. 一致性:对于任意的引用值x 和 y,如果用于equals比较的对象信息没有被修改, 多次调用x.equals(y)要么一致地返回true,要么一致地返回false
5. 非空性:对于任意的非空引用值x,x.equals(null)一定返回false
6. 重写hashCode:最好同时重写hashCode()方法,否则两个等价的对象可能得到不同的hashCode值,导致使用集合框架出现问题;

hashCode介绍:JDK根据对象的地址或者字符串或者数字算出来的int类型的数值,此方法主要是为了提高哈希表(例如 java.util.Hashtable提供的哈希表)的性能;

通过分析Hashtable的get()方法可以看出key键要同时满足hashCode值、key值,才能获得对应的value键;

public Object get(Object key) {    HashtableEntry e;    HashtableEntry tab[] = table;    int hash = key.hashCode();    int index = (hash & 0x7FFFFFFF) % tab.length;    for (e = tab[index]; e != null; e = e.next)        if ((e.hash == hash) && e.key.equals(key))            return e.value;        return null;}        

 

【Java基础】“equals” 和 “==”的理解