Object源码分析
java.lang.Object
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
类原型:
public class Object
静态代码块:
1.调用registerNatives()方法
static{
registerNatives();
}
方法:
2.
private static native void registerNatives();
registerNatives含义是本地注册的意思。
分析:该类有static,为静态方法,同时有native修饰。native表示该方法的实现java本身并没有完成,而是有c/c++来完成,形成.dll文件。 –摘自http://blog.youkuaiyun.com/qq_32169769/article/details/51842785registerNatives函数前面有native关键字修饰,Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。方法的具体实现体在dll文件中,对于不同平台,其具体实现应该有所不同。用native修饰,即表示操作系统,需要提供此方法,Java本身需要使用。具体到registerNatives()方法本身,其主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。 –摘自https://www.cnblogs.com/lwbqqyumidi/p/3693015.html ( 强烈推荐好好读一读这篇文章)
3.
public final native Class<?> getClass();
分析:final表示该方法不可被修改,而native表示由c/c++去完成。
而唯一知道的是该函数的的返回值为Class类的对象,表示返回调用该方法的对象的类
和java的RTTI和反射机制有关
4.
public native int hashCode();
分析:又是一个native方法,根据注释表示任何对象都有一个hashCode(),当他们的equals()一样时,hashCode()值必定一样。
通常是为了提高Hash表的性能才需要使用的
5.
public boolean equals(Object obj) {
return (this == obj);
}
分析:Object()类的惟二个(另一个是toString)不是抽象的方法,可以看出比较的是两个对象的地址
注意:
1.多个类重写了该方法(如所有的包装类和String,还有Date等。。。)
2.Java要求当两个对象的equals()相等时,他们的hashCode()必须相等,所以如果要重写equals()方法时,记得也需要重写hashCode()方法(eclipse中内置了快速生成对这两个方法的重写)
6.
protected native Object clone() throws CloneNotSupportedException;
分析:
注意该方法是protected,需要子类重写
该方法的功能是返回一个调用该方法的对象的一个‘副本’
clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。
clone()的正确调用是需要实现Cloneable接口,如果没有实现Cloneable接口,并且子类直接调用Object类的clone()方法,则会抛出CloneNotSupportedException异常。Cloneable接口仅是一个表示接口,接口本身不包含任何方法,用来指示Object.clone()可以合法的被子类引用所调用。
改正一个关于protected方法的误区:
关于好多国内java教材上说的对访问权限符protected和包权限的说明
教材上说如果一个类继承了其他包中的类,那么子类对象可以调用protected方法而不能调用包权限的方法
应该改为:如果一个类继承了其他包中的类,那么子类只能在定义的时候调用父类的protected方法,而不能通过子类对象调用。
若想通过子类对象调用,可以重写父类的protected方法,然后通过super调用即可
——(通过java根类Object
中的clone方法所得的思考
请仔细阅读下面的代码并分析
package com.lrr;
import com.protect.clone_base;
public class clone_test {
public static void main(String[] args) {
// TODO Auto-generated method stub
clone_child c = new clone_child();
c.test1(); //若clone_child没有重写test1(),则永远也调用不到父类的test1()方法
clone_child2 c2 = new clone_child2();
clone_child2 c3 = (clone_child2)c2.clone();
c3.test1();
}
}
class clone_child extends clone_base{ //clone_base 在另一个褒忠
protected void test1(){
super.test1();
}
void test2(){
//super.test2(); //error
}
}
class clone_base2{
protected void test1(){
System.out.println("clone_base2 test1()");
}
void test2(){
System.out.println("clone_base2 test2()");
}
}
class clone_child2 extends clone_base2 implements Cloneable{ //必须实现Cloneable接口,凡是这个接口没有任何一个抽象方法
protected void test1(){
super.test1();
}
void test2(){
super.test2(); //error
}
protected Object clone(){
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
7.
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
说明:返回类的名字+@+16进制的hashCode()值
也有好多类对其进行了重写,比如(容器类,输出的就是容器包含的对象的信息)
2017.12.5更新:
用System.out.println()输出一个对象时,编译器会默认调用该对象的toString()方法。
代码:
public class test1 {
Test1 rr =null;
public static void main(String[] args) {
test1 t = new test1();
//默认调用tostring
System.out.println(t); //Output:aaa
System.out.println(t.rr); //Output:bbb
}
public test1(){
this.rr = new Test1();
}
public String toString(){
return "aaa";
}
class Test1{
public String toString(){
return "bbb";
}
}
}
剩下的关于线程的几个函数,目前能力有限,还不能分析
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException
public final void wait() throws InterruptedException {
wait(0);
}
8.finalize():
protected void finalize() throws Throwable { }
说明:该函数与gc有关,当gc运行一次时,会将上一次已经打过标记的并且复活失败的对象回收,而在回收之前会默认调用该函数(表面上理解很像c++中的析构函数。不过很多书上都说这两种有显著的区别)
另:垃圾回收只和内存有关