java.lang.Object源码分析

一、Object类

Object类是Java中所有类的基类,在编译时会自动导入,位于java.lang包中,而Object中具有的属性和行为,是Java语言设计背后的思维体现。这里写的代码是JDK8中的,其他版本的JDK可能略有不同。 

二、Object构造方法 

Object类中没有显示的提供构造方法,这是编译器默认提供的。

三、Object类方法

Object类中的大部分方法都是native方法,用此关键字修饰的方法是Java中的本地方法,一般是用C/C++语言来实现。 

private static native void registerNatives()

其主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。函数的执行是在静态代码块中执行的,在类首次进行加载的时候执行。

private static native void registerNatives();
    /*对象初始化时自动调用此方法*/
    static {
        registerNatives();
    }

 public final native Class<?> getClass();

对象初始化时自动调用此方法

public native int hashCode(); 

返回对象的哈希码,是一个整数。这个方法遵守以下三个规则: 
1. 在java程序运行期间,若用于equals方法的信息或者数据没有修改,name同一个对象多次调用此方法,返回的哈希码是相同的。而在两次独立的运行java程序时,对于同一对象,不需要返回的哈希码相同 
2. 如果根据equals方法,两个对象相同,则这两个对象的哈希码一定相同 
3. 假如两个对象通过equals方法比较不相同,那么这两个对象调用hashCode也不是要一定不同,相同也是可以的。但是使用者应该知道对不同的对象产生不同的hashCode是可以提高hash tables的性能的。

在实际使用中,要尽量保证对于不同的对象产生不同的哈希码。hashCode的典型实现是将对象的内部地址转为一个整数,但是这种实现技术不是Java语言必须要采用的。

public boolean equals(Object obj) 

equals方法主要是比较两个对象是否相同,Object中的equals方法比较的是对象的地址是否相同。在我们实际的编程过程中,如果要是将一个类作为hashMap等类型的键值时,则此类是需要实现equals和hashCode方法,主要是用来比较键值是否相等以及进行哈希化。

public boolean equals(Object obj) {
        return (this == obj);
    }

protected native Object clone() 

clone方法是创建并且返回一个对象的复制之后的结果。复制的含义取决于对象的类定义。这个方法一般的意图是对于对象x,能够保证以下的表达式成立:

1. x.clone() != x;          2. x.clone().getClass() == x.getClass();                       3. x.clone().equals(x);

这些表达式一般都为true,但是并不是绝对需要的。 
按照惯例,返回的对象应该通过调用super.clone()来取得。如果一个类以及它所有的超类都服从这个惯例,那么x.clone().getClass()==x.getClass()成立。 
按照惯例,clone方法返回的对象是独立于调用clone方法的对象。为了获得这种独立性,在返回克隆对象之前,需要修改对象的成员变量。即如果我们要是复制可变的对象,内部的部分成员变量是由指定可变对象的引用组成,那么我们对这些成员变量也要进行clone复制,下面有例子说明。但是如果需要复制的类的成员变量是由基本类型或者由指向不可变对象的引用组成,那么我们不需要任何修改,直接对对象调用clone方法即可。 
如果一个类没有实现Cloneable接口(这个接口里面没有任何方法的声明,是一个标记接口),那么对此类的对象进行复制时,在运行时会出现CloneNotSupportedException异常。

扫描二维码关注公众号,回复: 4161685 查看本文章
protected native Object clone() throws CloneNotSupportedException;

更深入的学习关于深克隆及浅克隆的知识请转阅博主另一篇博文深入理解深克隆与浅克隆

public String toString() 

可以看到Object中toString方法的实现是返回类的名称(权限定名称)加上@,然后 加上此类的哈希码的16进制表示,例如:com.ll.client.House@2a139a55

public String toString(){
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

public final native void notity();

通知可能等待该对象的对象锁的其他线程。由JVM(与优先级无关)随机挑选一个处于wait状态的线程。 
- 在调用notify()之前,线程必须获得该对象的对象级别锁 
- 执行完notify()方法后,不会马上释放锁,要直到退出synchronized代码块,当前线程才会释放锁 
- notify()一次只随机通知一个线程进行唤醒 

public final native void notifyAll(); 

和notify()差不多,只不过是使所有正在等待池中等待同一共享资源的全部线程从等待状态退出,进入可运行状态 
让它们竞争对象的锁,只有获得锁的线程才能进入就绪状态 
每个锁对象有两个队列:就绪队列和阻塞队列 
- 就绪队列:存储将要获得锁的线程 
- 阻塞队列:存储被阻塞的线程

public final void wait()  

在Object中存在三种wait方法,可见wait()和wait(long timeout, int nanos)都在在内部调用了wait(long timeout)方法。

在其他线程调用此对象的notify()方法或notifyAll()方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行wait(0)调用一样。 当前线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用notify方法或notifyAll方法通知在此对象的监视器上等待的线程醒来,然后该线程将等到重新获得对监视器的所有权后才能继续执行。

public final native void wait(long timeout) throws InterruptedException;
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);
    }
    public final void wait() throws InterruptedException {
        wait(0);
    }

更深入的学习关于wait()方法的知识请转阅博主另一篇博文wait()和notify()深入剖析

猜你喜欢

转载自blog.csdn.net/qq_37141773/article/details/84136412
今日推荐