• JDK1.8源码学习-Object


    JDK1.8源码学习-Object

    目录

    一、方法简介

    1.一个本地方法,主要作用是将本地方法注册到虚拟机中。

    private static native void registerNatives();
        static {
            registerNatives();
        }

    2.获取类的字节码对象

    public final native Class<?> getClass();

    3.返回当前对象的hash值

     public native int hashCode();

    4.比较党当前对象的引用是否和要比较的对象的引用指向同一对象

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

    5.克隆对象,浅拷贝

    protected native Object clone() throws CloneNotSupportedException;

    6.返回当前对象的一个字符串表示形式

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

    7.唤醒一个正在等待该对象的线程,如果有多个线程等待,则只能唤醒其中一个

    public final native void notify();

    8.唤醒所有正在等待这个对象的线程

    public final native void notifyAll();

    9.阻塞当前线程,等timeout毫秒后会自动唤醒当前线程,当timeout为0时,表示不会自动唤醒线程

    public final native void wait(long timeout) throws InterruptedException;

    10.阻塞当前线程,等timeout毫秒后会自动唤醒当前线程,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.阻塞当前线程

        public final void wait() throws InterruptedException {
            wait(0);
        }

    12.当垃圾回收器确定该对象在任何地方没有被引用时,会调用此方法进行垃圾回收

    protected void finalize() throws Throwable { }

    二、方法详解

    1.equals方法

    在面试中经常会问道equals()方法和==运算的区别,==运算符用于比较基本类型的值是否相同而equals用于比较两个对象是否相等,在Object中equals与==是等价的,比较的是两个对象的引用,所以自定义对象的时候需要重写equals方法。在Java规范中,对equals方法的使用必须遵循以下几个原则:    

    • 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
    • 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
    • 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
    • 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改
    • 对于任何非空引用值 x,x.equals(null) 都应返回 false

      需要注意的是重写equals必须重写hashCode,且 

           X.equals(Y)==true,则X.hashCode()==Y.hashCode();

           X.hashCode()==Y.hashCode(),则X.equals(Y)不一定为true,也可能为false;

          具体原因可查看hashMap等集合源码。

     2. getClass方法 

          1.一个类的实例对象可以有很多,但是它的字节对象只有一个。

           2.一个对象可以被强转为其他对象但是其字节码不变。

    public class App {
        public static void main(String[] args) {
     
            Class clazz1 = new Person().getClass();
            Class clazz2 = new Person().getClass();
            Class clazz3 = Person.class;
     
            System.out.println(clazz1 == clazz2);//true
            System.out.println(clazz1 == clazz3);//true
     
            System.out.println(Object.class == (Object)(new Person()).getClass());//false
            System.out.println(Person.class == (Object)(new Person()).getClass());//true
     
        }
    }
     
    class Person{
     
    }

    3.clone方法

    浅拷贝与深拷贝的区别:

      浅拷贝:如果在一个对象的内部还有一个引用类型的变量,那么在拷贝对象的时候,clone方法新产生的对象只是拷贝了一个该基本类型的引用。

      深拷贝:如果在一个对象内部含有一个引用类型的变量,那么就会将该引用类型的变量指向的对象复制一份,然后引用该新对象。

      

    4.toString方法

    该方法返回一个能代表该对象的字符串,该字符串由类名以及该对象的十六进制的哈希值拼成。通常情况下,其子类需要覆写该方法。

    5.finalize方法

    垃圾回收器在认为该对象是垃圾对象的时候会调用该方法,子类可以通过重写该方法来达到资源释放的目的。

    在方法调用过程中出现的异常会被忽略且方法调用会被终止。

    任何该对象的方法只会被调用一次。

    总结

      本地方法7个:

                  private static native void registerNatives()

                  public final native Class<?> getClass()

          public native int hashCode()

          protected native Object clone()

                  public final void notify()

                  public final native void notifyAll()

                  public final native void wait(long timeout)

           非本地方法5个:

         public boolean equals(Object obj)

              public String toString()

           public final void wait(long timeout,int nanos)

           public final void wait()

           protected void finalize()

    思考点:notify、notifyAll、wait这些和多线程有关的方法为什么定义在Object类中?

                 1.在java的内置锁机制中,每个对象都可以成为锁,也就是说每个对象都是可以去调用这些方法的,而Object是所有类的父类,所以要把这些方法放到Object中。

                 2.一个线程可以拥有多个对象锁,上面这些方法跟对象锁之间是有一个绑定关系的,比如用对象锁aObject调用的wait()方法,那么只能通过aObject.notify()或者aObject.notifyAll()来唤醒这个线程,这样JVM很容易就知道该从哪个对象锁的等待池中去唤醒线程,假如用Thread.wait()、Thread.notify()、Thread.notifyAll()来调用,虚拟机则无法判断要操作的对象锁是哪个。

  • 相关阅读:
    Luogu3118:[USACO15JAN]Moovie Mooving
    Luogu4137:Rmq Problem/mex
    Luogu3092:[USACO13NOV]No Change
    BZOJ4321: queue2
    BZOJ4650 : [NOI2016]优秀的拆分
    webpack
    sublime eslint setup
    Sublime themes/ lint themes setup
    sublime text 3
    React
  • 原文地址:https://www.cnblogs.com/liudblog/p/11193963.html
Copyright © 2020-2023  润新知