【JDK8源码】java.lang.Oject类阅读笔记

【JDK8源码】java.lang.Oject类阅读笔记

前言

  • 爱美食的程序媛,能下厨房能敲代码,哈哈
  • 很少看源码,最近开始研究,或许有理解错误的地方,还望指正。

概述

Java中所有类的祖先,Java中所有的类包括我们自己定义的一些类,都会显式或隐式的继承Object类,任何一个类都可以调用Object中的非私有方法。

相关方法

1. registerNatives():void

  private static native void registerNatives();
   static {
       registerNatives();
   }
  • Object类的私有方法,不会被子类继承,并在静态代码块中执行,也就是在类进行初始化的时候就会执行
  • 使用了native方法修饰,说明这个方法是个原生函数,也就是底层是使用其他语言实现的,在JDK的源码中并不包含这些函数,主要是实现了像分配内存空间之类的这些操作

2. getClass():Class<?>

    public final native Class<?> getClass();
  • 同样使用native修饰,不允许重写,用来获取运行时对象(JVM内部做的)的class类实例,常用于反射。类似的还有:Class.forName(“类的全包名”)、类名.class。

3. hashCode():int

 public native int hashCode();
  • 返回该对象的哈希码值,int类型,通过内部转换,JDK源码的注解中说到默认是将对象的内存地址转换为一串整数(不是使用Java语言实现,具体需要导出Object的JNI头文件查看,此处不做深入研究)
  • 在应用程序的执行期间,一个对象没有被修改的前提下,多次调用时,hashCode必须返回相同的整数,如果两个对象的equals相等,那么hashCode一定是相等的,如果equals不相等,hashCode可能相等也可能不相等。
  • hashCode主要是用于哈希表中,比如HashMap、HashSet。

4. equals(Object):boolean

 public boolean equals(Object obj) {
      return (this == obj);
  }
  • 从上面的代码可以看出来,equals的判断使用了= =用来判断当前调用equals的对象和参数对象是同一个对象的,也就是说判断这两个对象指向的内存地址是否是同一块,如果是就返回true,否则返回false,就算内容完全相同,内存地址不同也返回false。
  • 不重写的话没有什么太大的意义,底层还是直接使用的= =判断,直接使用==也可以判断内存地址是否相同,一般都会重写(比如String类)。

5. clone():Object

    protected native Object clone() throws CloneNotSupportedException;
  • 也是本地方法,用来复制对象的,当一个对象调用该方法时,会返回一个与调用对象一摸一样的克隆对象
  • 该方法被声明为protected受保护的,也就是只有继承了这个类才可以使用这个方法,可以由子类重写该方法,扩大方法的访问范围。
  • 如果需要调用的clone()方法的话,调用类需要实现Cloneable接口(接口没有方法,类似于一个标志,标志可以使用clone方法),否则就会抛出异常提示无法克隆,比如之前有写过的集合类:ArrayList、LinkedList都有实现Cloneable接口。
  • 此处又涉及了深拷贝和浅拷贝,浅拷贝:外表变了,指向的还是原来的地址。深拷贝,把所有的东西都克隆一份,并且指向的不是同一个地址。那么Object的clone()是浅拷贝还是深拷贝呢,用代码测试一下看看
//Order类
@Data
public class Order {
   private  int id;
}

//user类
@Data
public class User  implements Cloneable{
  private String userName;
  private String userId;
  private Order order;
   public Object clone(){
       Object o=null;
       try {
           o=super.clone();
       } catch (CloneNotSupportedException e) {
           System.out.println(e.toString());
       }
       return o;
   }
}

//测试类
public class test {
   public static void main(String[] args) {
    User user=new User();
    Order order=new Order();
    order.setId(1);
    user.setOrder(order);
    user.setUserId("123");
    user.setUserName("JudyTest");
    System.out.println("克隆前:"+user.getUserName()+"--"+user.getOrder().getId());
    User user1=(User)user.clone();
    user1.setUserName("judyTest1");
    user1.getOrder().setId(2);
    System.out.println("克隆后:"+user.getUserName()+"--"+user.getOrder().getId());
   }
}

输出结果:
在这里插入图片描述
可以看到,如果是单个对象的话,那么是一种深拷贝,如果是对象的属性也是对象的话,那么对于这个属性对象来说又是一种浅拷贝。

6. toString():String

   public String toString() {
      return getClass().getName() + "@" + Integer.toHexString(hashCode());
  }
  • 就是把对象转换成一个字符串,如果不重写的话,默认输出的就是实例对象的类名+对象hashCode的十六进制,没有什么太大的意义,一般是重写,可以知道类里面的实际内容是什么

7. notify()、notifyAll()、wait():

都是在多线程时使用到的方法,为了配合synchronized使用的

//随机唤醒该对象等待集合中的任意一条线程
  public final native void notify();
  //唤醒该对象等待集合中的所有线程
  public final native void notifyAll();
  //调用wait()方法会导致当前对象等待,只有过了指定的时间,或者其他的线程调用了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);
  }

8. finalize():void

 protected void finalize() throws Throwable { }
  • protected修饰,受保护的方法,在垃圾回收时会调用对象的finalize方法(GC垃圾回收的时机具有不确定性,可能从头到尾都不会执行到),如果在垃圾回收之前让对象重新指向一个引用,那么就可以避免对象被回收,算是延长了对象的生命周期。但是并不是每次回收都会调用该方法,垃圾回收可能有多次,该方法只会调用一次。
  • 显然必须要重写才会有意义,因为Object中的finalize方法什么也没有写
  • 什么时候可能会用到,比如该对象处理的是一个非Java资源,像数Connection据库连接这样的忘记了close,就可以在Connection里实现finalize()方法,然后在里面调用close,不过一般情况都不会用到,也靠不住,因为调用了finalize并不代表这个对象就会被立马回收,可能已经调用了但又没有回收,等到下次真的要回收的时候又不能调用了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值