目录
在 java 中,只有基本类型不是对象,其它类都是 Object 类的子类。
Object 类
Object 类是所有类的父类,其中定义了以下方法
- clone () 复制一个一样的对象
- equals()
- toString () 默认输出包名。类名 @16 进制哈希值,一般需要被重写
- finalize () 用于回收对象
- getclass () 返回类(实际存储的类)
多线程方法
- notify()
- notifyall()
- wait()
equals()方法
默认的 equals()方法需要两个对象指向相同的对象。
一般情况下需要对 equals()方法进行重写。
对于字段中的对象需要递归地执行 equals()方法。
class extra{
}
public class Test {
int a;
extra b;
@Override
public boolean equals(Object obj) {
if(obj==null) return false;
if(getClass()!=obj.getClass()) return false;
Test test=(Test)obj;
return test.a==a && test.b.equals(b);
}
}
为了避免两个都是 null 的影响,可以使用 Objects.equals (Object a,Object b) 方法。如果两者均为 null 或指向相同对象,则返回 true。
相等测试
一般地,我们要求 equals () 方法满足自反律,传递律,对称律,一致性(多次测试返回同一结果)。
判断两者是否属于同一个类,有人喜欢用以下代码解决:
if(obj instanceof Test) return false;//Test为当前类
这种写法会引发一些问题,使 equals() 无法满足对称律。
因为 子类 instanceof 父类 和 父类 instanceof 子类 无法同时满足。
如果全部 instanceof 父类,必须忽略子类的部分信息。
- 但是,有时候我们需要判断两个不同类型的对象(继承自同一父类)是否在某些方面相等,比如 API 中两个集合 TreeSet 和 HashSet,它们只是存储方式不同,判断它们的集合元素是否相等时就需要使用 instanceof(此时需 instanceof 同一个父类)。此时,最好将 equals () 方法改为 final(但 API 中没有将其设为 final,因为集合的不同存储方式可以有更高效的算法)。
- 如果子类有自己的相等性概念,就应该使用 getClass () 方法。
equals(Object otherObject) 的一般写法
值得注意的是,otherObject 的类型必须为 Object,否则将不视作对 Object 类的方法的重写。
- 显式参数命名为 otherObject。
- 检测 this 和 otherObject 是否相等。
- 检测 this 和 otherObject 是否为 null。
- 用 instanceof 或 getClass 比较 this 和 otherObject 的类
- 将 otherObject 和 this 强制转化为某个共同父类(看需求)。
- 用 == 比较基本类型,用 equals () 比较对象,如果所有字段(或某些字段)都匹配,则返回 true,否则返回 false。
hashCode() 方法
散列码是由对象推出的一个整型值。
散列码是没有规律的,对于不同的两个对象,其散列码一般不会相同。
Object 类默认的散列码是由存储地址导出的。
在重写了 equals () 方法后一定要重写 hashCode () 方法。(因为改变了两个对象相等的定义,任意两个相等的对象的哈希值应该是相等的)
相比 hashCode (),Objects.hashCode () 更 null 安全。(如果输入 null,返回 0)
hashCode () 方法要综合各个字段的因素,使散列码的排列更加均匀。
一种较好的做法是,调用 Objects.hash () 并提供所有字段作为参数。hash () 方法组合了提供的所有字段的散列码(根据需要定义其中对象的 equals () 和 hashCode ())
toString()方法
默认输出 包名 . . .类名@hashCode()。
重写 toString()方法,一般返回值键对
“类名[字段名 1:字段值 1,…]”
在 print 方法中会将对象自动转化为 obj.toString ()
clone()方法
clone () 方法用于拷贝一个变量。
Object 类的 clone()方法是 protected 的,如果要在自己的类中使用必须要重写。
Object.clone()方法为 protected 的,重写的方法只能为 public 或 protected(不能为 default)。
public Student clone() throws CloneNotSupportedException{
return (Student)super.clone();//这样写出来的是浅拷贝
}
- 浅拷贝
Java 中默认的就是浅拷贝,会改变当前的对象,但对象中的对象字段是同一个。
clone 出来的对象不一样,但是其中的成员变量中对象是同一个。 - 深拷贝
对每个对象字段都重写 clone () 方法,在重写 clone () 方法时将对象中的每个对象字段进行浅拷贝。
数组类型
对于数组类型,可以用静态的 Arrays.equals (xxx [] a,xxx [] b) 判断两个数组是否相等。
可以用 Arrays.hashCode (xxx [] a) 计算数组的哈希值。
数组可以使用 Arrays.toString (xxx [] a),将数组转化为字符串,对于多维数组,要使用 Arrays.deepToString (xxx [] a)。
数组类型的 getClass() 方法
数组类型 getClass () 方法直接 print 会返回一些有点奇怪的名字。
[I 表示包含整型值的数组类型。同样的方式,其他基本数据类型的数组类型也可以使用类似的简写形式表示,例如:[B 表示字节数组类型,[C 表示字符数组类型,[D 表示双精度浮点数数组类型,[F 表示浮点数数组类型,[J 表示长整型数组类型,[S 表示短整型数组类型,[Z 表示布尔数组类型。
相对应的,[L 表示对象数组,其后接对象类型。