今天来学习java.lang包下的Object类,
Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
一般不显示继承,java是如何自动识别的呢?——>一般认为:JDK 6之前是编译器处理,JDK 7之后是虚拟机处理。
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:
显示继承:
public class Burns extends Object{
}
隐式继承:
public class Burns {
}
方法如下:
类的构造函数
Object(): 构造一个新对象
类加载执行的部分
static {
registerNatives();
}
类的方法
1. registerNatives()
private static native void registerNatives();
registerNatives本质上就是一个本地方法,但这又是一个有别于一般本地方法的本地方法,从方法名我们可以猜测该方法应该是用来注册本地方法的。对,你猜的没错。上述代码的功能就是先定义了registerNatives()方法,然后当该类被加载的时候,调用该方法完成对该类中本地方法的注册。这里你可能会有一些疑惑,比如,到底注册了哪些方法?为什么要注册?具体又是怎么注册的?
到底注册了哪些方法?
细心的你可能还会发现,在Object类中,除了有registerNatives这个本地方法之外,还有hashCode()、clone()等本地方法,而在Class类中有forName0()这样的本地方法等等。也就是说,凡是包含registerNatives()本地方法的类,同时也包含了其他本地方法。所以,显然,当包含registerNatives()方法的类被加载的时候,注册的方法就是该类所包含的除了registerNatives()方法以外的所有本地方法
为什么要注册?
一个Java程序要想调用一个本地方法,需要执行两个步骤:第一,通过System.loadLibrary()将包含本地方法实现的动态文件加载进内存;第二,当Java程序需要调用本地方法时,虚拟机在加载的动态文件中定位并链接该本地方法,从而得以执行本地方法。registerNatives()方法的作用就是取代第二步,让程序主动将本地方法链接到调用方,当Java程序需要调用本地方法时就可以直接调用,而不需要虚拟机再去定位并链接
具体怎么注册?
这个问题涉及到registerNatives()的底层C++源码实现,有兴趣可以自行研究
使用registerNatives()方法的三点好处:
- 通过registerNatives方法在类被加载的时候就主动将本地方法链接到调用方,比当方法被使用时再由虚拟机来定位和链接更方便有效;
- 如果本地方法在程序运行中更新了,可以通过调用registerNative方法进行更新;
- Java程序需要调用一个本地应用提供的方法时,因为虚拟机只会检索本地动态库,因而虚拟机是无法定位到本地方法实现的,这个时候就只能使用registerNatives()方法进行主动链接
- 通过registerNatives()方法,在定义本地方法实现的时候,可以不遵守JNI命名规范。那什么是JNI命名规范呢?举个例子,我们在Object中定义的本地方法registerNatives,那这个方法对应的本地方法名就叫Java_java_lang_Object_registerNatives,而在System类中定义的registerNatives方法对应的本地方法名叫Java_java_lang_System_registerNatives等等。也就是说,JNI命名规范要求本地方法名由“包名”+“方法名”构成,而上面的例子中,我们将Java中定义的方法名“g”和本地方法名“g_impl”链接了起来,这就是通过registerNatives方法的第四个好处。
2、getClass()
public final native Class<?> getClass();
运行时类就是jvm启动时,加载class文件生成的叫字节码对象,该对象建立后,后续通过创建类对象时,只需要根据字节码对象创建即可,不用每次创建都加载class文件,通过该Class也可以获取类的所有信息(方法,属性),可以说是class文件在虚拟机的快照。许多反射类应用都是基于此
3、hashCode()
public native int hashCode();
返回对象的哈希代码值:说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。一般应用在hashset,hashtable,hashmap,还有就是一般hashcode和equals方法结果要保持一致,
4、equals(Object obj)
public boolean equals(Object obj) {
return (this == obj);
}
Object中的equals方法是直接判断this和obj本身的值是否相等,即用来判断调用equals的对象和形参obj所引用的对象是否是同一对象,所谓同一对象就是指内存中同一块存储单元,如果this和obj指向的是同一块内存对象,则返回true,如果this和obj指向的不是同一块内存,则返回false,注意:即便是内容完全相等的两块不同的内存对象,也返回false。
java的equals()方法与“==”有什么区别?参考:juejin.cn/post/698087…
5、clone()
protected native Object clone() throws CloneNotSupportedException;
6、toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
7、notify()
public final native void notify();
8、notifyAll()
public final native void notifyAll();
9、wait(long timeout)
public final native void wait(long timeout) throws InterruptedException;
10、wait(long timeout, int nanos)
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos > 0) {
timeout++;
}
wait(timeout);
}
11、wait()
public final void wait() throws InterruptedException {
wait(0);
}
12、finalize()
protected void finalize() throws Throwable { }