1. 描述:
- Object类是类层次结构的根。每个类都有 Object作为超类。所有对象,包括数组等等
2. registerNatives()
private static native void registerNatives();
static {
registerNatives();
}
- 私有的本地方法,使用JNI调用其他语言,根据不同的操作系统调用对应的底层操作。
3. getClass()
public final native Class<?> getClass();
- getClass()返回对象的运行时Class对象。
- getClass()和 "类名.class" 都可以获取到Class对象,前者获得"运行时"的类对象,例如某对象多态情况下,实际对象为子类对象,这个对象调用getClass()获得的就是子类的class对象。后者则是类名的Class对象。如下代码。
Parent p = new Son();
System.out.println(p.getClass()); //Son
System.out.println(Parent.class); //Parent
4. equals()
public boolean equals(Object obj) {
return (this == obj);
}
- 源码中Object的euqals()就是"=="("=="对于引用对象来说是比较在栈内存中的引用地址,基本类型比较值),但使用时大多场景需要重写euqals(),例如String和自定义的bean等等。
- API中对equals()有如下描述(所有举例对象非null):
- x.equals(x)应该返回true
- x.equals(y)返回true时,当且仅当y.equals(x)返回true
- 如果x.equals(y)返回true、y.equals(z)返回true ,则x.equals(z)应该返回true
- 如果比较对象没有被修改,多次调用 x.equals(y) 始终返回 true 或始终返回 false
- 对于任何非空的参考值x , x.equals(null)应该返回false
- 重写equals()必须重写hashCode()!
5. hashCode()
- 返回对象的哈希码值(只是一个native方法源码就不贴出来了)。
- 集合类例如HashMap、HashTable中常借助哈希表来判断对象是否重复,避免全集合遍历扫描。最常见如HashMap放入数据就是取hashCode()然后根据map容量取余定位到具体的桶(bucket),如果桶里已有数据(hash冲突)则通过equals()判断是否相等,不相等就尾部添加变成链表,链表到达一定长度变成红黑树,以此进一步优化执行时间。
- API中对该方法描述:
- 在不影响equals()比较信息的情况下,多次调用hashCode()应返回相同整数
- equals()相等的两个对象,hashCode()的hash码必须相同(如果重写equals()不重写hashCode()会出现equals()相等hashCode()不等判断不出对象唯一的情况)
- equals()不相等的两个对象,也有可能hash码相同
- 从API中可得知在没被重写的情况下equals()相等(可以认为是同一对象),hashCode()一定相等,hashCode()相等对象不一定相等。不一定的原因是因为hashCode()是固定32长度的整形数字,对象可以随意生成肯定会比这个数字多,不可能一个对象对应一个hash码,但是量很少时hash码可以认为对象唯一,后面通过这个方法可以推测对象生成的情况,源码很多重写了hashCode(),可以借助System.identityHashCode()调用Object的hashCode()。
6. toString()
7. clone()
- 创建并返回此对象的副本。
- 这里涉及到两个概念"深拷贝"和"浅拷贝",常用类型有两种"引用类型"和"基本类型"。
- 引用类型:常见的自定义bean、数组等
- 基本类型:boolean、byte、char、short、int、float、long、double
- 引用类型存在栈,具体内容存在其他地方,例如堆。这样就出现个问题,引用类型如果只把栈的引用地址copy过去(浅拷贝Object.clone()),改变源数据就会导致所有引用的地方全部修改,如果能把源数据也copy一份的完全不影响这样就可以了(深拷贝,通常要重写clone()或反序列化实现)。
8. wait()
- API解释:导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。当前的线程必须拥有该对象的monitor。
- wait()、notify()、notifyAll()、是一组组合使用的方法,他们都需要获取对象的monitor(代码中常见就是各种锁,如synchronized)时才可以调用,释放锁有三种常见方式:
- 执行完同步代码块,自动释放。
- 运行同步代码块时遇到异常终止,异常释放。
- 运行同步代码块时,内部调用wait(),线程进入等待池。
- wait()释放锁的线程会进入等待池,必须经过其他线程调用notify()命中这个线程或notifyAll()才会继续和其他线程竞争执行机会,否则会一直等待,没权力竞争cpu调度。
- API中提到了一个写法问题,所有wait()和重载方法应该写在while循环中,循环条件是是否达到继续执行的条件,防止逻辑错误导致执行了不想执行的wait()线程。
9. wait(long timeout)
- wait()的重载方法,功能类似,只是设置一个timeout,超时后会自行唤醒,进而竞争cpu调度,当然如果等待期间notify()命中或notifyAll()也会激活。
10. notify()
- 如果等待池有线程,则随机唤醒其中一个
-
唤醒等待线程后不会立即释放当前锁,会执行完notify()所在的方法后才会释放锁,其他有权竞争执行的线程才会竞争。
11. notifyAll()
12. finalize()
- 当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象。 一个子类覆盖了处理系统资源或执行其他清理的finalize方法。
- 这个方法是在GC处理该对象时会调用的方法,通常可以重写finalize()做一些对象回收时的业务逻辑,一般很少用到。
网友评论