java8重写equals的不解?
在学Java中,遇到一个重写object类的equals方法,代码如下
public class Phone { public String name;
public int price;
public Phone(String name, int price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
//equaLs方法进行重写:
public boolean equals(Object obj) {
System.out.println(obj); //Phone@1b6d3586
if (obj instanceof Phone) {//是否属于Phone类的对象
Phone other = (Phone) obj;//将obj转为Phone类型:
if (this.getName().equals(other.getName()) && this.getPrice() == other.getPrice()) {
return true;
}
}
return false;
}
}
我定义了一个Phone类,有name和price两个属性,重写equals方法,只要name和price都一样就认为一样。
然后我测试了一下:
public class Test { public static void main(String[] args) {
Phone p1 = new Phone("P30",5000);
Phone p2 = new Phone("P30",5000);
System.out.println(p1.equals(p2)); //true
}
}
上面结果是true,达到效果,我不理解的是为什么需要Phone other = (Phone) obj;进行强转,在equals方法第一行我打印了obj结果是Phone@1b6d3586,那么是不是可以说明obj其实就是Phone的实列?如果是为什么需要强转?如果不是那么obj instanceof Phone结果是false也运行不进去啊?
回答:
在equals方法第一行我打印了obj结果是Phone@1b6d3586,那么是不是可以说明obj其实就是Phone的实列?如果是为什么需要强转?如果不是那么obj instanceof Phone结果是false也运行不进去啊?
是的没错,你传入的这个对象是Phone类型的一个实例,所以你不用怀疑为什么能进去if分支
接下来注意 你重写的是所有类的父类Object的equals方法,这个方法的形参是一个Object类型的对象,在JAVA里任何类型都是Object类型的子类,说白了这里只是告诉编译器什么类型都可以往里传,如果这里不是Object类型的形参,那你覆盖的就不是Object类的equals方法了而只是自己写了一个全新的equals方法,这当然也可以,而且比较的结果仍然是正确的,然而不重写Object类的equals方法的话,Java的标准库和其他第三方库通常依赖于equals方法的重写(Object类里的)来正确地比较对象,是会带来问题的。
好了现在问题变成为什么又要强转回去了,因为编译器现在只知道你传入的对象是一个Object类型的对象,我就偏偏不强转了怎么滴,可是Object类有getName()方法吗?有getPrice()方法吗?所以编译器就不乐意了,你只告诉我你是Object类型的你又没有这些方法,肯定就给你报错了。(不信你可以写一下试试,就不强转看看代码报不报红)
所以我们强转,告诉编译器其实刚才我只是装的,我只是为了满足你让我重写这个方法的门槛而已,现在我能重写这个方法了我就不演了,其实我是Phone哥,我有getName()方法和getPrice()方法,接下来就是就掏出自己的方法一顿操作了。
注意楼上有提及到你重写了equals方法就一定要重写hashCode方法,如果你不重写hashCode方法的话在把自定义对象丢进集合类的时候有意外的惊喜哦,至于为什么就不是这篇问题的范畴了,自行百度理解即可。
回答:
因为你在传入时的obj是Object类型, 你在下面需要调用Phone 类型, 因此需要用(Phone)做强转,
:
具体可以看我的这篇笔记,
Java 的多态:
https://segmentfault.com/a/1190000043455514
回答:
public boolean equals(Object obj) { if (obj instanceof Phone) {
Phone other = (Phone) obj;
if (this.getName().equals(other.getName()) && this.getPrice() == other.getPrice()) {
return true;
}
}
return false;
}
回答:
将你的代码转成 Kotlin
, 你会发现
class Phone(val name: String, val price: Int) { override fun equals(other: Any?): Boolean {
if (other is Phone) {
// 这块不需要再 (Phone)
return other.name == this.name && other.price == this.price
}
return false
}
}
但是将代码kt反编译后呢
public boolean equals(@Nullable Object other) { if (!(other instanceof Phone)) {
return false;
} else {
return Intrinsics.areEqual(((Phone)other).name, this.name) && ((Phone)other).price == this.price;
}
}
在JDK14之后,可以这样使用
@Datapublic class Mobile {
private String name;
private Integer price;
@Override
public boolean equals(Object other) {
// JDK14之后可以这样使用
if (other instanceof Mobile mob) {
return Objects.equals(mob.getName(), this.getName()) && Objects.equals(mob.getPrice(), this.getPrice());
}
return false;
}
}
回到这个问题本身。 https://stackoverflow.com/questions/4186320/why-cast-after-an-instanceof
public class A { public static void draw(Square s){...} // with implied cast
public static void draw(Object o){...} // without implied cast
public static void main(String[] args) {
final Object foo = new Square();
if (foo instanceof Square) {
// 这块会有兼容性问题
draw(foo);
}
}
}
另外:重写equals
后别忘记重写hashcode
以上是 java8重写equals的不解? 的全部内容, 来源链接: utcz.com/p/945175.html