Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java equals方法的错误实现模式_Java_Subclass_Equals - Fatal编程技术网

Java equals方法的错误实现模式

Java equals方法的错误实现模式,java,subclass,equals,Java,Subclass,Equals,我见过许多java equals()方法的实现,它们都遵循以下思路: public boolean equals(Object other){ if (this == other) return true; //this if code if (!(other intanceof MyClass)) return false; //ends here otherMyClass = (MyClass)other;

我见过许多java equals()方法的实现,它们都遵循以下思路:

public boolean equals(Object other){
    if (this == other) 
        return true;

    //this if code
    if (!(other intanceof MyClass))
        return false;
    //ends here

    otherMyClass = (MyClass)other;
    //check all the attribute of this and otherMyClass and return true or false
    //accordingly
}
if中的代码对于o1.equals(o2)(o1对象为MyClass,o2对象为MyClasss的子类)返回true,从这个意义上讲是否有问题?在大多数情况下,这不是预期的行为

不会
other.getClass()!=这个.getClass()
比上面的粗体更好吗?

如果(!(MyClass的其他intanceof))返回false,如果它们是不同类的实例,则返回false

我不能按照你的逻辑返回true,因为它不能返回true。但是,它可以计算为true,在这种情况下,将执行下一个语句。

o.getClass()!=getClass())
违反了Liskov替换原则

引用一位伟人的话:

Liskov替换原理认为 类型还应保留其子类型,以便任何方法 因为类型应该同样适用于其子类型


《有效的Java》一书中有关于这个主题的更多细节。

我认为最好的答案是@ChrisForrence(+1)的评论:


我想提醒您注意这样一个事实:使用
instanceof
会使
equals()
实现不对称:如果A是基类,而B扩展了A而没有定义任何其他字段或方法,那么
A.equals(B)==true
但是
B.equals(A)==false
其中
a
a
的实例,
b
b
的实例一年前我在一次采访中确实遇到了这个问题。我的实现也使用instanceof。我的面试官提到的关于使用getClass()==other.getClass()的两个论点突然出现在我的脑海中:

  • 在任何实际情况下,您可能永远不需要子类实例等于父对象;equals方法最常用于集合(更具体地说是集合);我在实践中从未遇到过这种情况,但如果有人在这里遇到过,请随意添加任何非纯理论情况作为评论,这些情况仍然适用(老实说,我很好奇是否有这种情况)
  • 记住equals合同的属性:
    • 反射的
    • 对称(*)
    • 传递的
    • 一致的
    • x、 对于任何对象x,等于(null)返回false
      • 在其他答案中已经指出了这一点:instanceof的对称性属性可能有问题(同样,在实践中,我很少使用包含不同类型元素的集合,但每当我有不同类型的元素时,我从一开始就知道对象实际上是不同的)

检查这个问题:但等式必须是可交换的(即
如果a==b,那么b==a
),在这种情况下可能不是这样。我认为你可以忽略
equals
方法的LSP…那么应该有一个专门为java equals()定义的liskov替换原则,如果一个类型的契约定义了一个等价关系,特别允许不同子类型的实例比较相等,然后,每个子类型都必须定义其equals方法来测试该等价关系,而不是其他等价关系。否则,关于LSP的任何内容都不表明必须能够创建任何特定类的实例,该类将自身报告为与任何其他对象等效,无论该对象属于同一类还是不同的类。对象的
getClass()
“值”作为比较基础的合法性不亚于其他任何东西。代码中没有“return true”,因此不会。是的,你是对的:)我同意!因此,getClass()是一种方法(在系统中明确定义了对象等价的概念之后)。@Razvan,听起来
getClass()
更好。尽管15年来我一直在使用
instanceof
equals()
中,但这是事实。。。但从其他情况来看,要小心。当一些类被框架广泛使用的代理包装时,这种技术可能会导致问题。