浅析java中“equals”和“==”区别

来源:互联网 发布:迪迦奥特曼act2.0淘宝 编辑:程序博客网 时间:2024/06/05 16:10

这两个方法肯定是用来比较两个对象引用的,java中new出一个对象后得到的是这个对象的地址,然后可以把这个地址赋给一个对象引用,也就是一个变量,通过这个变量我们可以直接操作这个对象,这一点可以联想C语言里面结构体指针利用  . 号操作结构体一样.举例说明:

A a1 = new A();

调用A类的构造器new出来一个对象,然后将这个对象在内存中的地址赋给a1变量,a1变量就可以操作刚new出来的对象了.

还有一种情况就是:没有将这个对象的地址赋给某个变量,而是直接传递给某个方法的形式参数,如:

假设有这样一个方法:

public void function(A a1);
为了调用这个方法,我们可以先创建一个对象并把它的地址赋给某个变量,然后再把这个变量传递给方法:
A a1 = new A();
function(a1);

这个过程其实是虚拟机先声明一个function的形式参数a1,然后将外部的局部变量a1中的对象的地址传递给形式参数a1,这时候两个a1指向的是内存中的同一个对象,方法调用完成后,function中的a1所占据的内存被释放,注意a1所指的对象所占的内存并没有释放.

另外一种方法是直接new出对象传递给方法:
function(new A());

这种方法其实跟上面的原理是差不多的,new出这个对象后虚拟机将这个对象的地址赋给了function中的形式参数a1,a1这个对象引用刚new出来的对象,function调用完成后a1和那个对象都会被释放内存.

关于对象引用差不多就是上面的内容,说上面这些内容的目的是告诉你==和equals能够比较对象的原理其实是通过对象引用来操作的,并不是直接通过对象,但是java中就是通过对象引用来表示对象的,所以也不要太过纠结对象引用和对象的区别了,new出一个对象赋给一个变量,你就可以把那个变量当做一个对象了.现在来说== 和 equals:

equals是Object超类中的一个方法,这个方法的实现就是通过==号实现的,==号比较的是两个对象的地址是否相同,在代码中体现出来就是比较两个对象引用中保存的地址是否相同,==能够判断的只是两个对象引用是不是指向同一个地址也就是同一个对象,所以它的相等判断是局限的:

A a1 = new A();A a2 = a1;这个时候a1 == a2是否为true?答案是yes,因为两个对象引用保存的是同一个对象的地址;
A a1 = new A();A a2 = new A();这个时候a1 就不 == a2了,因为两个对象引用指向的是不同的对象.
正因为==号只能判断两个对象引用是否指向同一个对象,所以决不能用它比较两个普通对象是否相等,即使两个对象所有的实例域都相同,虽然这在现实中的语义是两个对象指的是同一个事物比如同一个人,但是因为在代码中它们分配在不同的地址,所以用==号判断它们是不相等的.
学过c#的人都知道,c#是可以用==号进行字符串相等判断的,那是c#对==进行运算符重载了的,java中没有运算符重载,哦,有一个,就是+号,能够用来拼接字符串,所以java不能用==号进行字符串相等判断.

对于字符串,有必要深究一下,是不是所有的字符串都不能用==号进行判断了,答案是no:
虚拟机将字符串常量是共享的,所以对于引用字符串常量的变量是可以用==号判断的,但是字符串的其他操作比如new String("HelloWorld") + substring replace等产生的新字符串不是共享的,所以后面这些方法产生的字符串不能用==号进行判断.给出下面一个例子:
String hello = "hello';//hello是一个字符串常量的引用
if(hello == "hello")//true
    ...
if(hello.substring(0,3) == "hel")//false
    ...
上面的例子中"hello" 和 "hel"都是字符串常量.

那么要按照现实世界的语义来比较两个对象是否相等,比如两个字符串含有的字符个数一样,对应索引上的字符一样也一样我们就认为它们相等,而不是仅仅判断内存地址来决定,该怎么办呢?解决方法就是重写equals方法,前面说过了Object超类中的equals方法就是用==实现的,所以假如一个类没有重写equals方法,那么当应用a1.equals(a2)时,跟用==号判断是一样的,所以要根据对象的实例域来判断两个对象是否相等的话一定要重写equals方法,eclipse有快速生成equals的捷径,你用到它的时候就知道了.

有了equals方法以后,我们再进行相等判断就不是根据对象的地址了,而是看你怎么实现这个equals方法,

一般是根据对象的实例域来比较,比如姓名,身份证号,反正是一些特有或通用的属性,这个eclipse知道.

所以我觉得:

"=="只是对他们引用名称的比较,而"equals"是对他们的引用的内存地址做比较。


原创粉丝点击