Java中==与equals的区别
Posted Jerryoned
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中==与equals的区别相关的知识,希望对你有一定的参考价值。
要想理解它们俩之间区别,首先要了解一下它们的定义。
- ==比较的是变量(栈)中存放的对象(堆)的内存地址是否相同,即是否指向同一个对象。比较是真正意义上的指针操作。
- equals比较的是两个对象的内容是否相同,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
也就是说==是一个指针操作,用来比较数值相等,而equals则是一个方法,在Object类中equals方法中使用其实就是==,如果子类不重写equals方法,两者则并没有什么不同。
我们看Object类中equals方法如下:
public boolean equals(Object obj) { return (this == obj); }
对于==和equals我们需要分别从两种数据类型,基本数据类型和引用数据类型进行对比。
先说==,对于基本数据类型,也就是我们常说的int、char、long、short、boolean、double、float、byte这八种,他们之间的比较需要使用==,因为他们比较的是值。那它们可以使用equals方法嘛?不可以的,因为它们是基本数据类型,不是继承于Object类,自然也就没有equals方法之说。对于引用类型,==比较是变量中存放的对象的内存地址是否相同,所以除非是同一个new出来的对象,它们通过==比较出来的结果是true,因为每new一次都会开辟一块新的内存空间。
在说说equals方法,刚才说了对于基本数据类型是没有equals方法之说,对于引用数据类型,如果它没有重写equals方法,那还是沿用Object类中的equals方法,即实际通过==来进行比较,比较是变量中存放的对象内存地址是否相同。
==和equals方法之间的区别基本就是这些,下面说说一些特殊类堆Object中的equals方法进行重写的案例。
首先是String类,我们知道String是一种特殊的引用数据类型,比如以下代码,
String str1="Hello World";
String str2="Hello World";
那么如果比较str1==str2得到是true,因为字符串的值是final的不可改变的,相同的字符串在内存中只会存一份,所以str1和str2指向的内存地址是一样的。
如果写成这种形式呢?
String str1=new String("Hello World"); String str2=new String("Hello World");
此时再比较str1==str2得到是false,因为使用new关键字它们俩各自强行开辟了一块内存空间,这样str1和str2指向的内存地址是不一样。
对于equals方法,在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; }
在String类equals方法中首先是比较对象是否一样,如果一样则返回true,如果不一样再对比每一个字符是否一样,如果都一样,也同样返回true。
再看看Integer类,同样Integer类也对equals方法进行了重写:
public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
实际比较的还是两个基本数据类型(int)的值是否相等。
还有个细节的东西可以说明下,我们看下面代码的输出结果:
String str1="Hello"; String str2="Hello"; String str3=new String("Hello"); String str4=new String("Hello"); System.out.println("str1==str2?"+(str1==str2)); System.out.println("str1==str3?"+(str1==str3)); System.out.println("str3==str4?"+(str1==str2)); int a=1; int b=1; Integer i1=new Integer(1); Integer i2=new Integer(1); System.out.println("a==b?"+(a==b)); System.out.println("a==i2?"+(a==i2)); System.out.println("i1==i2?"+(a==b));
结果:
str1==str2?true
str1==str3?false
str3==str4?true
a==b?true
a==i2?true
i1==i2?true
对于字符串的对比可能不会有太大的意外,原因我们上面也都讲到了,只是对于“a==i2”这个为什么返回的也是true呢?难道变量a和i2存放的内存地址是一样的吗?这显然不正确,毕竟a是基本数据类型,存放的地址是栈中的地址,而i2是引用数据类型,存放的地址应当指向对中的地址。这是因为当Integer与int进行==比较时,Integer就会拆箱成一个int类型,所以还是相当于两个int类型进行比较,这里的Integer,不管是直接赋值,还是new创建的对象,只要跟int比较就会拆箱为int类型,所以就是相等的。其实所有的包装类在和其基本数据类型==比较时都会自动拆箱。
通过比较==和equals方法,我们发现,越是简单的东西,可能越不容易理解,越需要时间和精力去关注。
以上是关于Java中==与equals的区别的主要内容,如果未能解决你的问题,请参考以下文章
java中equals和equalsignorecase的区别