本篇文章将会对java中的Object类做一个简单的介绍,主要包括以下几个方面:
- Object类的基本信息
- equals方法
- toString方法
- hashCode方法
什么是Object类
java.lang.Object类是所有java类的超类,即无论是java中预定义的类还是自定义的类都会直接或间接的继承至Object类。而且如果在类的声明中未时使用extends关键字指明其父类,默认父类为java.lang.Object类。
并且通过查看java.lang.Object类的源码会发现,在java.lang.Object类中没有属性(即没有定义基本类型的变量),且只定义了一个空参的构造器
1 | public Object() {} |
下面介绍一些java.lang.Object类中一些已经定义的方法,这些方法都是在开发过程中需要自己进行重写的方法。
equals方法
equals方法用于检测一个对象是否等于另一个对象。但是如果我们直接调用Object方法中定义的equals方法,得到的往往不是我们想要的结果:
1 | public static void main(String[] args) { |
毫无疑问第一个打印的将会是false,因为A和B显然不是同一个引用,而==比较的就是引用中存储的地址。而对于第二个打印,我们期待的是true(他们的属性完全一样,在现实生活中指代的东西因该是相同的),但是出人意料的是第二个打印语句依然会打印false,这是为什么呢?看一下源码:
1 | public boolean equals(Object obj) { |
没错,在object类中定义的equals方法默认使用的就是==进行判断的。
但是在大多数情况下我们希望equals方法比较的是两个对象的属性是否完全相同,这是就需要在自定义类中进行重写。
Java语言1规范要求equals方法具有下面的特性:
- 自反性:对于任何非空引用X,X.equals(X)因该返回true
- 对称性:对任何非空引用x和y,当且仅当y.equals(x)返回true,x.equals(y)返回true
- 传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true
- 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果
- 对于任意非空引用x,x.equals(null)应该返回true
在写equals方法的一般步骤是:
- 显式参数命名为otherObject,稍后再将他强制转换成另一个名为other的变量
- 检测this与otherObject是否相等
1 | if(this = otherObject) return true; |
- 检测otherObject是否为null,如果null,返回false。
1 | if(otherObject == true) return false; |
- 比较this与otherObject的类。如果equals方法可以在子类中重写,就可以使用getClass检测,如果所有的子类比较的都是父类中的属性,可以使用instanceof检测。
这主要是为了满足对称性的要求,getClass方法返回一个对象所属的类。也就是说使用getClass方法进行判断将会两个对象是否属于同一个子类。而使用instanceof方法进行判断,将允许一个父类与一个子类相等
1 | animal c = new dog(14,"jone","sds"); |
- 将otherObject强制转换为相应类类型的变量
1 | ClassName other = (ClassName)otherObjece; |
- 根据相等性概念的要求依次比较字段
1 | public boolean equals (Object otherObject) { |
equals方法也可以通过软件自动生成(alt+shift+s)
1 |
|
hashCode方法
散列码是由对象导出的一个整型值(有可能是一个负数),Object类的默认hashCode方法会从对象的存储地址得出散列码。
如果我们重写equals方法,就必须为用户可能插入散列表的对象重新定义hashCode方法。
为了避免不同的对象产生相同的散列码,就要使用合理对实例字段的散列码进行组合,以使得不同对象产生的散列码分布更加均匀。
一个简单而又好用的方式是使用Objects.hash方法。该方法可以对每个参数调用Objects.hashCode方法,并进行组合
1 | public int hashCode() { |
也可以直接使用软件快捷生成,以下就是快捷生成的:
1 | public int hashCode() { |
toString方法
在之前的程序或者实例中由很多次需要将对象的详细信息进行显示。当我们需要输出一个对象的引用时,实际就是调用当前对象的toString方法。该方法能够将对象的所有对象转换成字符串形式进行输出。
在Object中也定义了一个toString方法
1 | public String toString() { |
可以看到这里输出的内容是:类名+@+用十六进制表示的散列码
1 | System.out.println(A.toString());//cons.animal@31e32f |
这显然不是我们实际期待的返回内容,所以我们需要对这个方法进行重写。
绝大多数的toString方法所遵循的格式是:类的名字+一对方括号括起来的各个对象的值。
1 | public String toString() { |
1 | System.out.println(A.toString());//animal[namejone, age = 14] |
但是这并不是一个很好的写法,当其子类需要使用toString方法时,需要对该方法进行全部的重写,因为类名不够准确。但是有些属性又是父类中有的。所以我们可以使用下面的写法:
1 | public String toString() { |
1 | System.out.println(A.toString());//cons.animal[name=jone, age = 14] |
1 | System.out.println(C.toString());//cons.dog[name=jone, age = 14][cry=sds] |
本文链接: https://quandongli.github.io/post/9742ed3b.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
