Why verify obj class does not match instance class before typecasting in Java?
我想使用一个自定义的equals方法比较两个人的统计数据,该方法将覆盖对象类中的equals方法。因为这个equals方法的返回类型是一个布尔值,所以我知道需要传入(object obj)参数。当我定义新的equals方法时,我被告知我需要首先检查obj类是否与实例类匹配。一旦验证了这一点,我输入将obj类转换为实例类,并可以继续执行其余的代码。
但是,我不理解为什么我需要验证obj类与实例类不匹配。我认为这两个类应该不匹配,因此需要类型转换。
有人能告诉我为什么我们需要验证obj类与实例类不匹配吗?我正在处理的代码写在下面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public boolean equals (Object obj ) {
if (obj == null || obj. getClass() != this. getClass())
return false;
else {
Person pp2 = (Person ) obj ;
if (this. name. equals(pp2. name) && this. age == pp2. age)
return true;
else
return false;
}
}
public static void main (String[] args ) {
Person ps1 = new Person ("Buddy", 14);
Person ps2 = new Person ("Buddy", 14);
if (ps1. equals(ps2 ))
System. out. println("Same");
} |
- 可能有两个具有相同变量的不同类。学生和人,都有名字和年龄,但他们是不同的班级。
- 在sidenode上,使用obj instanceof Person将同时执行这两项操作,检查类是否相等,如果obj不为空
- 由于ps2来自person类,而obj来自object类,那么在您键入cast之前,类匹配验证是否总是在调用ps1.equals.ps2时失败?这就是我困惑的原因。
- @omarn ps2.equals(new person())将生成person的obj实例。所以getClass将返回Person类。
- 明白了,明白了。谢谢您!
你建议做的是:
1 2 3 4
| public boolean equals (Object obj ) {
Person pp2 = (Person ) obj ;
return (this. name. equals(pp2. name) && this. age == pp2. age);
} |
这将违反equals()方法契约,该契约明确指出,当两个对象不相等时,该方法必须返回false。这里不是这样的:该方法将改为抛出一个ClassCastException(或者,如果obj为空,则抛出一个NullPointerException)。
- 但是,既然我们在调用(ps1.equals(ps2))时通过equals传递ps2,而ps2属于person类,这是否意味着类类型将不匹配,因为obj属于对象类?因为它们不匹配类,所以我不理解为什么我们要检查它。
- 人是物体。把一个人当作一个对象并不改变它的类型:它仍然是一个人,并且由obj.getClass()返回的实际类仍然是人。这就是多态性。它在现实生活中起作用。虽然你的手机是iPhone6s,但我可以把它称为"手机"、"电子设备"或"物体",这并不能改变它仍然是iPhone6s的事实。
- 好吧,我想我明白了。所以验证成功是因为对象类等于Person类,因为Person是对象的子类?
- 几乎。您可以将Person实例作为对象引用,因为类人员扩展了类对象。这就是为什么你可以打电话给equals()和一个人争论的原因。obj.getClass()返回类人,因为obj实际上是类人的一个实例。如果obj是对dog实例的引用,它将返回类dog。但狗也可以被称为一个对象,因为它也扩展了对象。
- .equals(null);将引发NullPointerException而不是ClassCastException。
- @塞德波尔,你考虑过阅读答案吗?是这样说的。明确地说。
- 明白了,完全有道理,谢谢!
- @很抱歉,我改为读(或改为读)。然后,我认为新的问题是stackoverflow.com/questions/2887761/…
如果您不检查其他obj的类型,那么当有人呼叫时,您可能会得到ClassCastException
你不想那样。你想返回错误而不是崩溃。
你可以使用:
1 2
| if (obj instanceof Person){
} |
- 使用instanceOf而不是检查类标识将违反equals的约定,因为它破坏了对称性。
- @德鲁尼克斯:可能,是的。但您可以匹配所有其他子类的equals实现来保持对称性。事实上,这实际上是由像List这样的事情来完成的。它们应该是相等的,即使容器类是不同的。