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之后,可以这样使用

@Data

public 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

回到顶部