JDK源码分析之Object

摘要

Java作为一种面向对象(Object Oriented)的编程语言,一切事物都可以看成对象,而Object是java一切Class的父类,也就是说,java中一切除Object的class都继承自Object,因此对Object类的理解对于学习java有着至关重要的意义。

从类方法看Object

java设计者将几乎所有的类都需要的高频使用的方法集成到一个超类中,这就是Object,Object中含有的方法如下:

public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj);
protected native Object clone();
public String toString();
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout);
public final void wait(long timeout, int nanos);
public final void wait();
protected void finalize();

getClass()

在Object类中,getClass()方法被关键字native修饰,表明其实现使用了JNI(java
native interface),本文对此不作深入了解。
此方法与java反射机制有关,可以得到类的详细信息(类名,类方法等),在之后涉及到class Class再详细解析。

hashCode()

从方法声明可以得知,hashCode()返回了一个int值,此int值便是调用此方法的实例的哈希值。对于含有容器类型的程序设计语言来说,哈希值至关重要。
在java中,这样的容器数据类型有HashMap,HashTable,HashSet。当插入一条记录时,如何保证插入的数据是否已经存在,如何快速找到需要的数据成为最重要的问题。三种数据类型中都有形如 <K,V>的数据结构,在HashMap与HashTable中是Entry<K,V>[] table,HashSet中则是HashMap<E,Object> map,其中的K值便通常是类实例调用hashCode()方法产生的int值,称为散列值。
getClass中提到,native修饰的方法是本地方法,其实现与JVM的实现有关,hashCode()生的值同样与虚拟机有关,通常来说,与对象的存储地址有关。(有时间再补充)
虽然可以用hashCode来表示对象,但不能仅凭hashcode相同来证明两个对象是一致的。所以在散列表的设计中需要涉及到解决冲突算法。

equals

从Obejct中equals的实现
public boolean equals(Object obj) {
return (this == obj);
}

可以得知返回的是传入对象与当前对象引用地址是否一致,对于java基本类型(String,Integer等),都对equals()进行了重写,保证了比较引用地址的同时还比较存储的数值。所以一般编写自己的类时需要用到equals()时,应该重写方法,否则可能出错。

clone()

同样是本地方法,返回一个Object,顾名思义,这是一种克隆对象的方法,返回的是当前对象的克隆。
这里我们知道创建对象也可以使用clone()方法。我们知道操作符“=”同样可以将新对象指向同一对象引用
测试如下代码:

Apple app=new Apple();
app.setName("红苹果");
Apple app1=app;
Apple app2=app.clone();
System.out.println(app);
System.out.println(app1);
System.out.println(app2);

其中class Apple必须重写clone(),实现Cloneable接口。
输出如下:

Apple@610455d6
Apple@610455d6
Apple@511d50c0

可见操作符“=”仅仅将同一对象的引用指向新对象“app1”,堆区没有创建新对象,而clone()直接在堆区创建了新对象。

toString()

看Object中的实现
return getClass().getName() + "@" + Integer.toHexString(hashCode());
返回“类名@hashcode()值的16进制表示”,hashcode()的生成与地址有关,所以可以一定程度上反映当前对象再内存上的存储状态。
通常我们使用自己创建的类的toString方法时,会将需要了解的类的信息打印出来,而不仅仅是类名和hashcode。

wait()

此方法在Object中声明为final,无法重写,由JVM实现。是多线程编程中重要的方法。
有三个重载

public final native void wait(long timeout);
public final void wait(long timeout, int nanos);
public final void wait();

某对象调用wait()方法后,当前线程阻塞(此线程必须拥有该对象的monitor),释放锁,等待被唤醒。
1.wait():当前线程阻塞,直到被唤醒。
2.wait(long time):当前线程阻塞,直到其他线程调用此对象的 notify()方法或 notifyAll()或超过设定时间
3.wait(long timeout, int nanos):当前线程阻塞导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

notify()

此方法在Object中声明为final,无法重写,由JVM实现。是多线程编程中重要的方法。
唤醒在此对象监视器上等待的单个线程。

notifyAll()

唤醒在此对象监视器上等待的所有线程。

finalize()

垃圾回收器准备释放内存的时候,会先调用finalize()。

小结

本文从Obejct的类方法初步分析了java编程中常用的方法用途及其实现,助于进一步理解Object。更多的细节没有详细阐述,日后会有进一步的更新。不足之处,多多指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值