Object是我们非常熟悉的一个类了,它是所有类的基类,一个类即时没有直接继承任何类,它默认也会继承Object类,也就是所有的类都直接或者间接的基础了Object类,这就是说Object类是所有类的基类的原因
Object是java.lang下的类,细心的小伙伴可能都已经发现了,该包下的所有类在使用的时候都不需要手动导入,系统会在编译的时候自动导入,类似的还有Integer、String类等都是属于这个包下的
一、Object类的结构图
1、Object类的七大native方法:registerNatives()、getClass()、hashCode()、clone()、notify()、notifyAll()、wait(long)
native关键字修饰的方法称为本地方法,这些方法并不是用java实现的,考虑到实现的性能问题,大多是由C/C++编写的程序,编译成dll文件,再由java去加载这些dll文件,就可以通过java来调用dll中的函数了
1)**registerNatives()方法:**主要是将用C/C++语言写的一些方法,如hashCode、wait、notify等方法加载到jvm中,感兴趣的可以去OpenJDK中查看相关C的代码如下
static JNINativeMethod methods[] = {
{“hashCode”, “()I”, (void *)&JVM_IHashCode},
{“wait”, “(J)V”, (void *)&JVM_MonitorWait},
{“notify”, “()V”, (void *)&JVM_MonitorNotify},
{“notifyAll”, “()V”, (void *)&JVM_MonitorNotifyAll},
{“clone”, “()Ljava/lang/Object;”, (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,methods, sizeof(methods)/sizeof(methods[0]));
}
2)**getClass()方法:**我们可以看到这个方法是由final修饰的,因此不能被重写的,对final关键字不太了解的,可以看一下我的另一篇文章:Java源码解析之 final关键字的使用详解
//class 是一个类的属性,能获取该类编译时的类对象
System.out.println(Bird.class);//class com.somta.test.commonuseobj.objectobj.Bird
//getClass() 是一个类的方法,它是获取该类运行时的类对象
System.out.println(bird.getClass());//class com.somta.test.commonuseobj.objectobj.Bird
3)hashCode()方法:返回一个整数的HashCode值,该值依赖于内部表示堆的对象的指针,一般情况下,该方法都会被重写。关于hashCode与equals的关系,我们只需要记住下面四句话(前提:需要重写equals和hashCode方法,String、Integer、Boolean、Double等都重写了这两个方法,不重写HashCode方法,任何对象的hashCode都是不相等的,并且equals方法也会使用Object中的equals方法,此时equals和==是等价的,equals比较的是栈中的引用,而非对象的值)
1、如果两个对象相等,则它们的hashCode值一定相等
2、如果两个对象不相等,则它们的hashCode值不一定都不相等
3、如果两个对象的hashCode值相等,两个对象不一定相等
4、如果两个对象的hashCode值不相等,两个对象一定不相等
4)clone()方法: 将一个对象克隆出一个新对象,要实现clone的对象一般需要先实现Cloneable接口才能达到克隆的目的,克隆其实也分“浅克隆”,“深克隆” ,Object类的克隆属于“浅克隆”,关于克隆的知识,后续在写文章说明,此处就不展开了
5)notify()、notifyAll()、wait(long)方法: 这些方法后续在多线程中在具体讲解
2、Object类的常用方法:equals()、toString()
1)、equals()方法
我们可能在以前的面试中被问到过关于 == 和 equals的区别,可能大多人的回答是:“==运算符通常是用来比较基本类型的值是否相等或者比较对象的引用是否相等;equals比较的是两个对象是否相等”,这种说法其实并不太正确,不妨我们先看Object中关于equals()方法的源码
public boolean equals(Object obj) {
return (this == obj);
}
Object类是所有类的子类,如果一个类没有重写equals()方法,那它就会使用父类的的equals()方法,通过上面的代码可以看出其实在Object类中,==运算符和equals()方法是等价的,其实上面的说法只适用于那些重写了Object类equals方法的类而言是正确的,比如String等。
注意:重写equals()方法的时候,必须要重写hashCode方法,以维护hashCode的约束,确保equals()方法声明相等的对象具有相同的hashCode值
2)、toString()方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
getClass().getName()返回了该类的全类名,Integer.toHexString(hashCode())返回了以16进制无符号整数的形式返回了此hashCode的字符串,这个是根类Object的实现,子类中一般都会重写该方法