zoukankan      html  css  js  c++  java
  • Object 源码解析

    Object的源码结构如下,Objec有以下方法

    public class Object {
    
        private static native void registerNatives();
        static {
            registerNatives();
        }
    
        public final native Class<?> getClass();
    
        public native int hashCode();
    
        public boolean equals(Object obj) {
            return (this == obj);
        }
    
        public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
        }
    
        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;
    
        protected void finalize() throws Throwable { }
    }
    

      

    1、public final native Class<?> getClass();

    getClass是一个native方法,final的不允许子类重写

    返回当前运行时对象的Class对象,如下定义的n类型为Number,但是Java中默认的类型为Integer类,所以返回的是java.lang.Integer

            Number n = 0;
            System.out.println(n.getClass());  // class java.lang.Integer
    

      

    2、public native int hashCode();

    hashCode也是一个native方法

    哈希码的通用规约如下:

    1. 在java程序执行过程中,在一个对象没有被改变的前提下,无论这个对象被调用多少次,hashCode方法都会返回相同的整数值。对象的哈希码没有必要在不同的程序中保持相同的值。
    2. 如果2个对象使用equals方法进行比较并且相同的话,那么这2个对象的hashCode方法的值也必须相等。
    3. 如果根据equals方法,得到两个对象不相等,那么这2个对象的hashCode值不需要必须不相同。但是,不相等的对象的hashCode值不同的话可以提高哈希表的性能。

    通常情况下,不同的对象产生的哈希码是不同的。默认情况下,对象的哈希码是通过该对象内部地址转换成一个整数来实现的。

    String的hasCode方法实现如下:

    public int hashCode() {
            int h = hash;
            if (h == 0 && value.length > 0) {
                char val[] = value;
    
                for (int i = 0; i < value.length; i++) {
                    h = 31 * h + val[i];
                }
                hash = h;
            }
            return h;
        }
    

    hashCode的源码如下

    static inline intptr_t get_next_hash(Thread * Self, oop obj) {
      intptr_t value = 0 ;
      if (hashCode == 0) {
        // 根据Park-Miller伪随机数生成器生成的随机数
         value = os::random() ;
      } else
      if (hashCode == 1) {
         // 此类方案将对象的内存地址,做移位运算后与一个随机数进行异或得到结果
         intptr_t addrBits = cast_from_oop<intptr_t>(obj) >> 3 ;
         value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;
      } else
      if (hashCode == 2) {
         value = 1 ;            // 返回固定的1
    } else
      if (hashCode == 3) {
         value = ++GVars.hcSequence ;  // 返回一个自增序列的当前值
      } else
      if (hashCode == 4) {
         value = cast_from_oop<intptr_t>(obj) ;  // 对象地址
      } else {
         // 通过和当前线程有关的一个随机数+三个确定值
         unsigned t = Self->_hashStateX ;
         t ^= (t << 11) ;
         Self->_hashStateX = Self->_hashStateY ;
         Self->_hashStateY = Self->_hashStateZ ;
         Self->_hashStateZ = Self->_hashStateW ;
         unsigned v = Self->_hashStateW ;
         v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;
         Self->_hashStateW = v ;
         value = v ;
      }
    
      value &= markOopDesc::hash_mask;
      if (value == 0) value = 0xBAD ;
      assert (value != markOopDesc::no_hash, "invariant") ;
      TEVENT (hashCode: GENERATE) ;
      return value;
    }
    

     java6、7默认返回随机数

    java8默认是通过当前线程相关的一个随机数+三个确定值,运用Marsaglia’s xorshift scheme随机三方得到一个随机数。 

    参考:https://blog.csdn.net/changrj6/article/details/100043822

      

    3、equqls方法

    public boolean equals(Object obj) 

    比较两个对象是否相等,Object类的默认实现,就是比较2个对象的内存地址是否相等

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

    equals方法在非空对象引用上的特性

    1)、reflexive,自反性。任何非空引用值x, 对于x.equals(x)必须返回true

    2)、symmetric,对称性。 任何非空引用值x和y,如果x.equals(y)为true,那么y.equals(x)也必须为true

    3)、transitive,传递性,任何非空引用值x、y和z,如果x.equals(y)为true,并且y.equqls(z)为true, 那么x.equqls(z)也必定为true

    4)、consistent,一致性。任何非空引用值x和y,多次调用x.equals(y) 始终为true或者始终为false,前提是对象上equals比较中所用的信息没有被修改

    5)、对于任何非空引用值x, x.equals(null)都应返还false

    4、clone方法

    protected native Object clone() throws CloneNotSupportedException;

    clone是一个native方法,一般情况下,对于任何对象x, x.clone() != x 为true, x.clone().getClass() == x.getClass() 也为true

    5、toString()方法

    Object对象的默认实现,即输出类的名字 @实例哈希码的16进制

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

     

    6、notify方法 

    public final native void notify();

    是一个native方法, 并且是final不允许子类重写

     唤醒一个在此对象监视器上等待的线程(监视器相当于锁的概念)。一个线程在对象监视器等待可以调用wait方法。

    7、public final native void notifyAll();

    和notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。

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

    wait是native方法,也是final的,不允许子类重写

    wait方法会让当前线程等待直到另外一个线程调用对象的notify或者notifyAll方法,或者超过参数设置的timeout超时时间。

    9、public final void wait(long timeout, int nanos) throws InterruptedException;

    和wait方法一样,多了一个参数 nanos 毫微秒 

    10、public final void wait() throws InterruptedException;

    没有超时时间的wait方法

    11、finalize方法

    默认实现是不进行任何操作

    protected void finalize() throws Throwable { }

  • 相关阅读:
    MySQl数据约束练习
    MySQL查询实例
    网络通信协议简介(TCP与UDP)
    数据类型转换
    C++编译过的C代码为什么要用extern C
    hashtable
    以RB-tree为底层机制的几个关联式容器
    红黑树(RB-Tree)
    slist
    deque
  • 原文地址:https://www.cnblogs.com/linlf03/p/12624924.html
Copyright © 2011-2022 走看看