OOP中的身份和平等有什么区别?
OOP(面向对象编程)中的身份和平等有什么区别?
-
身份:一个variables与另一个variables保持相同的实例。
-
平等:两个不同的对象可以互换使用。 他们经常有相同的ID。
例如:
Integer a = new Integer(1); Integer b = a;
a
与b
相同。
Integer c = new Integer(1); Integer d = new Integer(1);
c
与d
相等但不相同。
当然,两个相同的variables总是相等的。
在Java中,相等是由equals
方法定义的。 请记住,如果你实现equals,你还必须实现hashCode 。
身份确定两个对象是否共享相同的内存地址。 平等决定两个对象是否包含相同的状态。
如果两个对象是相同的,那么它们也是相等的,但仅仅因为两个对象是相等的,并不意味着它们共享相同的存储器地址。
对于string有一个特殊的情况,但这是一个脱离主题,你需要问别人有关如何工作确切;-)
身份意味着它是相同的对象实例,而等于意味着您比较的对象是对象的不同实例,但碰巧包含相同的数据。
插图(在Java中)
Date a = new Date(123); Date b = new Date(123); System.out.println(a==b); //false System.out.println(a.equals(b)); //true
所以a和b是不同的实例(内存中的不同分配),但是在“数据”级别上它们是相等的。
考虑“相同”和“等同”这两个字。 如果两件事是相同的,它们具有相同的身份; 他们是一样的东西。 如果它们是相同的,则可以替代另一个而不影响结果; 他们有相同的行为和属性。
例如,
在StackOverFlow中:
-
身份:我是迈克尔,你是塞万加拉扬,所以我们不一样。
-
平等:如果我们有相同的信誉分数,我们在某些方面是平等的。
在Java和类似的语言中“泄露”对象引用的抽象,你可以testing两个引用是否引用同一个对象。 如果他们引用同一个对象,那么引用是相同的。 在Java中,这是==
运算符。
还有一个equals
方法用于testing两个对象是否具有相同的值,例如当用作HashSet
键时(相等对象的哈希码也应该相等)。 当客户端代码使用时,相同的对象应该具有相同的“值”和语义。
Purer面向对象的语言没有标识符比较,因为客户端代码通常不应该关心两个对象是否具有相同的内存地址。 如果对象表示相同的现实世界的实体,那么使用一些ID或者键值而不是身份来更好地build模,然后该实体成为等价合同的一部分。 不依赖于对象的内存地址来表示真实世界的标识,从而简化了caching和分布式行为,并且抑制了==
会在string比较中删除大量的错误,或者在Java中对一些基元进行装箱。
标识:对同一个对象的两个引用( o1 == o2
)。
平等:方法o1.equals( o2 )
返回true
。 这并不一定意味着这两个对象包含(全部)相同的数据。
从理论上讲,即使对于相同的对象,也可以重写equals()
方法来返回false
。 但是这会破坏Object.equals()
的规范:
equals方法在非null对象引用上实现等价关系:
- 它是自反的:对于任何非空引用值x,x.equals(x)应该返回true。
- 它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才返回true。
- 它是可传递的:对于任何非空引用值x,y和z,如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)应该返回true。
- 这是一致的:对于任何非空引用值x和y,如果在对象的等值比较中没有使用修改的信息,那么x.equals(y)的多个调用始终返回true或始终返回false。
- 对于任何非null的引用值x,x.equals(null)应该返回false。
一些链接:
- http://today.java.net/pub/a/today/2006/07/27/defining-object-identity.html
- http://ocw.mit.edu/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-170Fall-2005/D659DC53-FB1D-403C-8E35-2CAECBED266E/0/lec12.pdf
- http://kentreis.wordpress.com/2007/02/08/identity-and-equality-in-ruby-and-smalltalk/
For primitive types ( int , boolean , char, long , float ... )
==和!=是平等testing
and for Objects
==和!=是身份testing。 [只比较参考]
equals
方法用于对象的相等性testing[可以重写比较特定属性]
引用
我喜欢猪。 狗看着我们。 猫看不起我们。 猪对待我们是平等的。 :d
Sir Winston Churchill
身份概念是相当哲学的,这就是为什么你不应该只参考它。
你可以说,两个身份是相同的,如果第一个变化反映在第二个,反之亦然。 当然,这也包括共享相同的内存地址,但是一般而言,身份与对象的属性相关,只要两个对象相同,但是不包括身份,等同性就用来检查。
反之亦然,如果两个项目具有相同的身份,他们也是平等的(平等互换)。
只有在variablesx
和y
引用相同的对象时, x == y
为真。
x.equals(y)
取决于x.equals()
的实现,而且通常比上面那样严格,因为它比较了对象的内容。 (在Java中,如果x.equals(y)
,它也必须是真正的x.hashCode() == y.hashCode();
)
例:
Integer w = new Integer(3); Integer x = new Integer(1); Integer y = x; Integer z = new Integer(1); // all of these evaluate to true y.equals(x) // it's the same object, of course the content is same x.equals(z) // different objects, same content (`1`) z.equals(y) !w.equals(x); // the content is different (`3` vs `1`) !w.equals(y); !w.equals(z); x == y // same object z != x // different objects y != z w != x
看看我的video,这解释了身份和平等之间的区别很好,包括两个一步一步的编码示例: https : //www.youtube.com/watch?v=OOpO46_k7Uo