equals和==的区别
有Java基础的人都会搞懂一个问题就是equals和==的区别是什么.我的文章便从这开始谈起。首先我要告诉你equals和==是完全一样的。你可能非常不赞同。请看下面的代码
public boolean equals(Object obj) {
return (this == obj);
}
显然这段代码印证了我刚才的话。那么这段代码从何而来呢,它是object类的一个方法,也就是equals的原形。至于我们所用到的equals和==不一样。很简单equals被重写了。我们用到的equals方法不是Object的,而是他的子类的。当然有一个很重要的问题被我忽视了,也就是==比较的是jvm的堆中对象的位置,简单的说就是对象的地址,而不是对象的内容。
重写equals方法的类不止一个我们看看下面的这几个。
<!--EndFragment-->
下面看一下和==有点关系的两个代码:
Integer i1 = 200;
Integer i2 = 200;
System.out.println("i1==i2: "+(i1==i2));
和
Integer i3 = 100;
Integer i4 = 100;
System.out.println("i3==i4: "+(i3==i4));
这两代码很简单,说一句废话,如果你懂,就会感觉答案很简单,不懂,就傻眼了,哈哈。
<!--EndFragment--> 这两段代码的结果是:
i1==i2: false
i3==i4: true
"==" 比较的是两个对象的引用(内存地址)是否相同,也用来比较两个基本数据类型的变量值是否相等。
在自动装箱时对于值从-128到127之间的值,它们被装箱为Integer对象后,会存在内存中被重用,
所以范例中,i3 与 i4实际上参考至同一个对象。
如果超过了从-128到127之间的值,被装箱后的Integer对象并不会被重用,
即相当于每次装箱时都新建一个 Integer对象,所以范例中,i1与i2参考的是不同的对象。
另外,当不使用自动装箱功能的时候,情况与普通类对象一样,请看下例:
Integer i3 = new Integer(100);
Integer i4 = new Integer(100);
System.out.println("i3==i4: "+(i3==i4));//显示false
<!--EndFragment--><!--EndFragment-->
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
这个方法是Integer中的方法,显然这个比较的是对象的内容,即某一Integer对象的值。而不是对象地址了。自然这个时候equals和==就不一样了。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
这个是String中的equals方法。因此可以这样解释一下,所要判断的String对象,如果是同
一个对象,则返回true,如果不一样,但是内容一样,也会返回true。
关于equals方法的重写有几条规则:
1)自反性:对于任何非空的引用x',x.equals(x) 应该返回true。
(这也是String中重写equals时,第一个判断的原因)
2) 对称性:对于任何引用x和y,如果x.equals(y)返回true,反过来亦成立。
3) 传递性:对于任何引用x、y和z,如果x.equals(y)返回
true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
4) 一致性:如果x和y引用的对象没有发生变化,那么反复调用
x.equals(y)应该返回同样的结果。
5) 对于任意非空引用x,x.equals(null)应该返回false。
下面是对重写equals方法的一些建议:
下面给出编写一个完美的equals方法的建议:
1) 显式参数命名为otherObject,稍后需要将它转换成另一个叫
做 other的变量。
2) 检测this与otherObject是否引用同一个对象:
if (this == otherObject) return true;
这条语句只是一个优化。实际上,这是一种经常采用的形
式。因为计算这个等式要比一个一个地比较类中的域所付
出的代价小得多。
3) 检测otherObject是否为null,如果为null,返回false。这项
检测是很必要的。
if (otherObject == null) return false;
比较this与otherObject是否属于同一个类。如果equals的语
义在每个子类中有所改变,就使用getClass检测:
if (getClass() != otherObject.getClass()) return false;
如果所有的子类都拥有统一的语义,就使用instanceof检测:
if (! (otherObject instanceof ClassName)) retrun false;
4)将otherObject转换为相应的类类型变量:
ClassName other = (ClassName)otherObject;
5) 现在开始对所有需要比较的域进行比较了。使用 == 比较
基本类型域,使用equals比较对象域。如果所有的域都匹
配,就返回ture;否则返回false。
return field1 == other.field1
&& field2.equals(other.field2)
&& ……;
<!--EndFragment--> <!--EndFragment-->
上一篇: JavaWeb服务器-Tomcat
下一篇: 软件构造 面向可维护性的设计模式