zoukankan      html  css  js  c++  java
  • 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()来调用,虚拟机则无法判断要操作的对象锁是哪个。

  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/liudblog/p/11193963.html
Copyright © 2011-2022 走看看