重写equals()!

kahnnash 2010-08-11 10:36:35
public class TestEquals{
public static void main(String[] args){
Student stu = new Student();
Teacher tea1 = new Teacher("Robin");
Teacher tea2 = new Teacher("Robin");
System.out.println(tea1.equals(tea2));
System.out.println(tea1.equals(null));
System.out.println(tea1.equals(stu));
}
}
class Teacher{
String name;
public Teacher(String name){
this.name = name;
}
public boolean equals(Object obj){//<======================对象进入以后是什么类型的?引用是Object 对象呢?
if(obj == this) return true;
if(obj == null) return false;
if(!(obj instanceof Teacher)) return false;//<==================这里不太懂,stu到了这里能编译过?不是父类对象 instanceof 子类 才返回false,然后条件成立?=====
Teacher t1 = this;
Teacher t2 = (Teacher)obj;//<===========还有这里
return t1.name.equals(t2.name);
}
public int hashzCode(){
return name.hashCode();
}
}
class Student{

}
...全文
749 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
kahnnash 2010-08-13
  • 打赏
  • 举报
回复
楼上诸位的讲解小弟都看了 太感谢了

今天看了一下core java上的一些内容 上面说instanceof不能解决子类对象的问题,在子类和父类中都覆盖equals()的话,无法实现对称性

调用的对象和参数不能互换 a.equals(b)和b.equals(a)返回的结果不一样

所以如果只允许同一类型的对象相等最好用getClass()
bekeer 2010-08-13
  • 打赏
  • 举报
回复
首先来说对象的内容与对象的引用存储位置:
对象的内容是存储在堆中的 而对象的引用是存储在栈中的 而栈中即引用中存储的实际上是对象本身在堆中的地址
其次说说equals
equals是object中的方法 由于object是根类 所有的类都默认的继承了object类 所以也就继承了equals方法 但是在object类中的equals方法仅仅是比较的两个两个对象的地址是否相同 例如有对象a和b
if(a == b) object中的equals只是实现了这一步而已 因为当a与b相等时 说明他们指向的是同一个堆地址 那就说明a和b所指代的内容肯定是相同的
再次说说为什么要重写equals
由于在某些实际中 跟看重的是两个对象的内容是否相同 意思是说虽然a和b的地址不同 但是他们的内容却相同
所以就需要equals来判断内容了 所以在非object类中就要重写equals了 来判断看a和b的地址是否相同 同时也得加上判断内容是否相同
在来说说==
==只是比较的地址 if(a == b)如果是true说明a和b指向的是同一个地址 如果是false 则说明a和b指向的不是同一个地址但不能说明a和b的内容不同 如果用==来比较非对象 例如比较 int x;int y;(值类型即非对象是保存在栈中的 用==来比较两个值类型时时直接比较值的而不是其指向的地址 由于在栈中保存的是值而不是地址 所以比较的是值 )if(x == y)如果是true的话说明x和y的值相同 否则值不相同
总结:
==是比较的实际存储的内容 对象的引用在栈中的内容是地址(这个地址是对象本身在堆中的地址)所以用==比较两个对象是比较的对象本身在堆中的地址
而值类型在栈中存储的就是他的值 例如 int x= 10;在栈中保存的x的内容就是10 所以在比较值类型的时候是比较的值

这是lz的代码:
public boolean equals(Object obj){//比如说有Teacher t1= new Teacher() t.name = “abc” 你就可以把t串进来 这时就是 Object obj = t;由于Object是所有类的父类 所以obj可以用来实例化所有子类的对象
if(obj == this) return true;//这句是用来比较t1和this所指向他们所引用的对象本身在堆中的地址
如果相同 则说明他们所指向的是同一个地址 而同一个地址中的内容是唯一的 所以他们两个所引用的内容肯定相同 return true以后 后面的代码就不执行了 结束此方法
if(obj == null) return false;
if(!(obj instanceof Teacher)) return false;//这里的意思是 如果t1不是Teacher的对象 就返回false 并结束此方法 例如 Student s = new Student();那是肯定不是Teacher的对象了 那肯定不会相同 因为他们的堆地址肯定不一样 内容就不一定了
Teacher t1 = this;
Teacher t2 = (Teacher)obj;//这就是多态性了 这就好比某个人有一个儿子一个女儿 并且有两样东西 一个要传个儿子另一个要传个女儿 在他死后 儿子和女儿发现了这两个东西 如果这个人没立遗嘱也没有在东西上写上哪个是儿子的 哪个是女儿的 那这两个人就不知道该怎么办了 所以就得立遗嘱或是写明确哪个是儿子的 哪个是女儿的 这里的Teacher t2 = (Teacher)obj就是说明要将obj传个Teacher类型的对象 向下转型
return t1.name.equals(t2.name);//这一步就是比较内容的了 当上面的几个if都不执行的话就会执行到这步 执行到这步就意味着 他们的地址不同 并且obj也是Teacher的对象
}
jiahao0321 2010-08-12
  • 打赏
  • 举报
回复
郁闷 本来挺明白的 进来一看又晕了。。。 建议LZ在回到对象转型开始--》继承--》equals

最起码你应该知道object类 是所有类的根基类
an5168 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 tujiazu 的回复:]
对象进入以后是什么类型的?引用是Object 对象 ----->?this对象调用这个方法,和超级父类 比较
对象==对象 ,比较的是内存地址。不能这么比较两个对象是否相等。首先你可以 if(obj.getClass ==this.getClass)...
然后比较对象的属性
if(this.属性.equals(参数.属性)) .....


Teacher tea1 = n……
[/Quote]顶这位同志
yktd26 2010-08-12
  • 打赏
  • 举报
回复
找了段代码解释了instanceof几乎所有的情况
class A { 
int i, j;
}
class B {
int i, j;
}
class C extends A {
int k;
}
class D extends A {
int k;
}
public class InstanceOf {
public static void main(String args[]) {
A a = new A();
B b = new B();
C c = new C();
D d = new D();
if(a instanceof A)
System.out.println("a is instance of A");
if(b instanceof B)
System.out.println("b is instance of B");
if(c instanceof C)
System.out.println("c is instance of C");
if(c instanceof A)
System.out.println("c can be cast to A");
if(a instanceof C)
System.out.println("a can be cast to C");
System.out.println();
// compare types of derived types
A ob;
ob = d; // A reference to d
System.out.println("ob now refers to d");
if(ob instanceof D)
System.out.println("ob is instance of D");
System.out.println();
ob = c; // A reference to c
System.out.println("ob now refers to c");
if(ob instanceof D)
System.out.println("ob can be cast to D");
else
System.out.println("ob cannot be cast to D");
if(ob instanceof A)
System.out.println("ob can be cast to A");
System.out.println();
// all objects can be cast to Object
if(a instanceof Object)
System.out.println("a may be cast to Object");
if(b instanceof Object)
System.out.println("b may be cast to Object");
if(c instanceof Object)
System.out.println("c may be cast to Object");
if(d instanceof Object)
System.out.println("d may be cast to Object");
}
}
yktd26 2010-08-12
  • 打赏
  • 举报
回复
如果不这样那么instanceof的结果不等于true就是一个错误了?
yktd26 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 kahnnash 的回复:]
哦。。。编译的时候student为左边类型,所以不出错。
运行时为右边类型,但运行时为什么不报错?[/Quote]
运行时报错啊,错误就是检查到student不是一个Teacher类的实例,所以返回false啊
如果喜欢可以写成
if (!student instanceof Teather){
throw new Exception("student is not an instance of Teacher Class");
}

那就成了异常了
kahnnash 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 yktd26 的回复:]

引用 15 楼 kahnnash 的回复:
如果你能理解为什么可以People student = new Student();
其实student instanceof Teacher是差不多的道理啊,instanceof是个运算符,如果
People student = null能编译,为什么People student = new Student();不能编译?
编译器并不关心student将会指向一个什么对象,那是运行的时候的事情
但最终instanceof所比较的确实对象,而不是你这个People类型的引用
……
[/Quote]
哦。。。编译的时候student为左边类型,所以不出错。
运行时为右边类型,但运行时为什么不报错?
jklzhou 2010-08-12
  • 打赏
  • 举报
回复
学习了!
yktd26 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 kahnnash 的回复:]
Java code
public class TestInstanceof{
public static void main(String[] args){
People people = new People();
People student = new Student();
People tea = new Teacher()……
[/Quote]
如果你能理解为什么可以People student = new Student();
其实student instanceof Teacher是差不多的道理啊,instanceof是个运算符,如果
People student = null能编译,为什么People student = new Student();不能编译?
编译器并不关心student将会指向一个什么对象,那是运行的时候的事情
但最终instanceof所比较的确实对象,而不是你这个People类型的引用
yktd26 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 kahnnash 的回复:]
引用 13 楼 yktd26 的回复:

对啊
方法是对象的,目的是比较对象
可是你传递的是引用,引用是比较的手段

那所有类型的对象进入equals后,它们的引用不都变成Object类型的了吗
[/Quote]
是,局部引用是Object类型的,没错啊
kahnnash 2010-08-12
  • 打赏
  • 举报
回复
public class TestInstanceof{
public static void main(String[] args){
People people = new People();
People student = new Student();
People tea = new Teacher();
Teacher teacher = new Teacher();
System.out.println(student instanceof Teacher);//其实就是想问这里为什么没有编
//译出错而且还返回了false
System.out.println(tea instanceof Teacher);//而这里返回true。这俩对象的引用都
//是People
// System.out.println(teacher instanceof Student);
}
}
class People{

}
class Student extends People{

}
class Teacher extends People{

}
kahnnash 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 yktd26 的回复:]

对啊
方法是对象的,目的是比较对象
可是你传递的是引用,引用是比较的手段
[/Quote]
那所有类型的对象进入equals后,它们的引用不都变成Object类型的了吗
yktd26 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 kahnnash 的回复:]
引用 11 楼 yktd26 的回复:

当然反过来说如果
Java code
String s = new String();
System.out.print(s instanceof Number);

不能编译
但是你equal方法中的obj是Object类型引用
所以没问题


有点明白了 但是前面不是说 比较的是对象吗?这里还与引用有关系?
[/Quote]
对啊
方法是对象的,目的是比较对象
可是你传递的是引用,引用是比较的手段
kahnnash 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yktd26 的回复:]

当然反过来说如果
Java code
String s = new String();
System.out.print(s instanceof Number);

不能编译
但是你equal方法中的obj是Object类型引用
所以没问题
[/Quote]

有点明白了 但是前面不是说 比较的是对象吗?这里还与引用有关系?
yktd26 2010-08-11
  • 打赏
  • 举报
回复
当然反过来说如果
String s = new String();
System.out.print(s instanceof Number);

不能编译
但是你equal方法中的obj是Object类型引用
所以没问题
yktd26 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kahnnash 的回复:]
引用 4 楼 yktd26 的回复:


第二个地方判断的是对象是不是Teacher类型,这里instanceof比较的是对象不是引用,所以如果对象不是Teacher类型直接返回,这合情合理啊

stu instanceof Teacher 编译应该不会过吧
当obj引用指向new Student()时
!(obj instanceof Teacher) 也应该不会过的啊!!!
[/Quote]
你传到方法里面的引用是Object类型的
Object s = new String();
System.out.print(s instanceof Number);

这肯定能编译通过
bekeer 2010-08-11
  • 打赏
  • 举报
回复
public class TestEquals{
public static void main(String[] args){
Student stu = new Student();
Teacher tea1 = new Teacher("Robin");
Teacher tea2 = new Teacher("Robin");
System.out.println(tea1.equals(tea2));
System.out.println(tea1.equals(null));
System.out.println(tea1.equals(stu));
}
}
class Teacher{
String name;
public Teacher(String name){
this.name = name;
}
public boolean equals(Object obj){//<==============这里传入的是Object对象 由于Object是所有类的父类 obj可以由任何类来是实例化 这就是多态性的表现 obj可以转型成任何类的对象 所以这里的意思是可以传入任何对象if(obj == this) return true;
if(obj == null) return false;
if(!(obj instanceof Teacher)) return false;//<==================instanceof是判断obj是不是Teacher类的对象的 这里前面有个"!" 所以正好相反
Teacher t1 = this;
Teacher t2 = (Teacher)obj;//<===========这就是第一个注释那说的 obj可以转型成任何类 向下转型 这部分内容要好好看了 我是又看书又看视频还没理解透return t1.name.equals(t2.name);
}
public int hashzCode(){
return name.hashCode();
}
}
class Student{

}

我的理解仅供参考 可能有误 还处于入门阶段
yktd26 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 yktd26 的回复:]
引用 5 楼 kahnnash 的回复:
hashCode()在这里没用的。。

instanceof判断改为 getClass() == obj.getClass()//我用Eclipse生成了一下也是这样

但是 那个instanceof 好像也能打印正确结果呢?

这里instanceof和getClass() == obj.getClass()没什么区别,不用改
[/Quote]
也不能这么说
instanceof允许子类比较name
getClass() == obj.getClass()直接返回false
这得看你的设计
kahnnash 2010-08-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yktd26 的回复:]


第二个地方判断的是对象是不是Teacher类型,这里instanceof比较的是对象不是引用,所以如果对象不是Teacher类型直接返回,这合情合理啊
[/Quote]
stu instanceof Teacher 编译应该不会过吧
当obj引用指向new Student()时
!(obj instanceof Teacher) 也应该不会过的啊!!!
加载更多回复(6)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧