您的位置:首页 > 编程语言 > Java开发

Java:Java中的同一性和等同性

2015-10-14 11:48 381 查看

同一性(identity):

java提供了判等运算符:==和!=,可以作用于基本数值类型,boolean型数值,引用类型.例如:

两个引用ref1和ref2引用了相同的对象或者都是null,那么表达式ref1==ref2的值为true,就算这两个引用具有不同的类型声明也是如此,否则表达式的值为false.

判等运算符测试的是引用的同一性,而不是对象的等同性.若两个引用指向同一个对象,那么它们是同一的.若两个对象逻辑上拥有同样的值,那么它们是等同的.等同性是通过Object定义的equals方法来进行检验的.对于那些等同性和同一性不是一回事的类,应覆盖equals方法,因为:

Object.equals假定一个对象只和它本身等同.

注意:

由于数组没有定义自已的方法,仅仅继承了Object的方法,所以其equals方法总是基于同一性而不是等同性,java.util.Arrays类中的equals方法是通过计算基于数组内容的散列码来比较数组的等同性.

等同性(equivalence):

Object中的equals比较:

比较接受者和参数对象的内存位置,若子类没有提供equals实现,那么使用缺省的比较内存位置的equals实现.Java API文档关于Object的equals方法的部分,提供了一个列表,详细的定义了两个对象之间的相等关系:

1.自反性(reflexivity):x.equals(x)

2.对称性(symmetry):x.equals(y) 当且仅当y.equals(x)

3.传递性(transitivity):如果x.equals(y) 并且y.equals(z),那么:x.equals(z)

4.一致性(consistency):给定一致的状态,x.equals(y)返回一致的结果

5.可以与null比较(comparison to null):x.equals(null)

相关应用:

1.参数为null的情况下返回false的防卫子句

@override
public boolean equals(Object object){
if(object == null) return false;
...
}


2.apple and orange

如果有人向方法扔进一个”orange”,立即返回false防卫(bg)子句,该防卫子句确保参数的类型与接受者的类型相匹配

@override
public boolean equals(Object object){
if(object == null) return false;
if(this.getClass() !=object.getClass()) return false;
...
}


3.为什么不用equals?

类常量是唯一的:所有类对象共享一个实例,正因为类常量的唯一性,所以可以使用判等运算符 != 来比较类常量,而不必一定使用方法equals.

当然也有人更倾向于 instanceof,如果某个对象是目标类的实例,或者目标类的子类实例,那么操作符 instanceof返回true.如下:

public boolean equals(Object object){
if(object == null) return false;
if(!(object instanceof User)) return false;
...
}


推荐使用方法getClass而不是instanceof,来比较两个类的类型,只有两个对象属于同一个类,getClass才返回:true,若需要在继承层次上不考虑层次位置的比较对象,那就使用instanceof

4.字符串字面常量,等同性和内存限定

一般来说使用判等运算符:==,来比较字符串会得到错误的结果.然而对于两个相同内容的字符串字面常量来说,他们将指向同一个String对象,例如:

String str="abc";
if(str=="abc"){
....
}


注意:

只有当所涉及的所有字符串引用指向的都是字符串字面常量时,才可以这么作,如果str改成引用一个生成的String对象,那么==判等运算符就返回false.为了解决这个问题,可以对不能确切知道是否引用到了字符串字面常量进行内存限定(intern).

intern方法:

该方法将返回一个String对象,它与被调用该方法的String对象是具有同样的内容,然而任何两个内容相同的字符串在被调用intern方法后,返回的String对象都是相同的,这种机制使得我们可以通过比较字符串引用来测试其等同性,从而取代执行速度极慢的对字符串内容的测试.

int putIn(String key){
String unique=key.intern();
int i;
for(i=0;i<tableSize;i++)
if(table[i]==unique) return i;
table[i]=unique;
tableSize++;
return i;
}


对intern方法的返回结果进行处理,使得对对象引用的比较等价于对字符串内容的比较,但前者运行速度更快.尽管两个不同的字符串,可能具有相同的散列码,但是任何两个内容相同的字符串都应该具有相同的散列码,因此String类覆盖了Object.hashCode方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: