jdk源码每日一读 (一) java.lang.Object

jdk源码每日一读 (一) java.lang.Object

1. 类说明

Object是java继承体系的根,是每一个类的基类,所有的类都实现了Object类的所有方法。

2.重要方法

public final native Class<?> getClass()
public native int hashCode();
public boolean equals(Object obj);
protected native Object clone() throws CloneNotSupportedException;
public String toString();
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;

3. 分析

  1. getClass方法

    getClass方法的返回值是Class对象,它返回的是对象消除静态类型的类型,也就是说他返回的是对象的实际类型,比如说下面这个例子

    public class Test {
        public static void main(String[] args) {
           A a=new B();
           System.out.println(a.getClass());
        }
    }
    class A{
    
    }
    class B extends A{
    
    }

    B是A的子类,虽然a声明的类型是A,但是getClass方法返回的类型是B

  2. hashCode方法

    该方法返回的是一个整形的hash码,一般这个方法用于利用到散列的类,比如说hashmap等,支持这个方法是为了提高hash表的性能。源码中强调了,如果两个类使用equals方法比较相等,那么hashCode的返回值一定相同,但是如果使用equals方法比较不同,不对hashCode的返回值是否相等做要求,但是不同对象的hashCode不相同能够提高hash表的性能。

    在同一个应用中,每次调用同一个对象的hashCode方法,返回的整数一定相等。

    hashCode是一个本地方法,他的返回值与对象的地址有关。

  3. equals方法

    比较两个对象是否相等,在Object的实现中,直接使用==比较两个对象是否相等,也就是说比较的是两个对象的地址是否相等,如果有特殊的要求,如字符串的内容相等则可以认为两个字符串是相等的,那么应该重写equal方法,当然也不要忘记重写hashCode方法。

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

    重写equal方法要满足下列要求

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

    返回该对象的副本,对于一般类,必须实现Cloneable接口,该接口是一个标记接口,里面没有内容。

    public interface Cloneable {
    }
  5. toString方法

    返回一个表示该类信息的字符串,需要子类去重写toString方法,默认实现如下: 类名[email protected]+哈希码的16进制字符串

     public String toString() {
            return getClass().getName() + "@" + Integer.toHexString(hashCode());
    
  6. notify方法

    随机唤醒在此对象监视器上等待的其中一个线程。

  7. notifyAll方法

    唤醒在此对象监视器上等待的所有线程

  8. wait方法

    调用wait系列方法,当前线程将会等待,并放弃该对象的监视器的所有权,调用该方法之前当前线程必须拥有该对象的监视器的所有权。

  9. finalize方法

    当垃圾回收器确定不存在对该对象的更多引用时(该对象可以被回收),由对象的垃圾回收器调用此方法。子类可以重写该方法,使得该对象避免被回收,具体的做法是让该对象再次存在引用,但是注意该方法只能被调用一次。

4. 问题

  1. 为什么重写equals方法要重写hashCode方法

    个人理解:hashCode方法在被设计的时候就是为了提高与hash相关的数据结构的性能,具体是如何提高的呢?以HashMap为例,当需要查找某个元素的时候,HashMap判断某个key是否相等的时候,为了速度,首先是判断的hashCode是否相等,然后通过equals方法判断是否相等。所以如果重写了equals而没有重写hashCode就会造成不一致性,也就是说通过equals方法判断两个对象是相等的,而hashCode未重写的时候默认返回的值与对象的地址有关,这样hashCode势必就不相等了。所以为了保证比较时的一致性在重写equals方法的时候一定要重写hashCode方法,这一点在hashCode方法的源码注释里也说明了。

  2. clone方法在什么情况下使用

    个人理解:clone用来复制一个对象,在java中创建一个对象有很多方式,比如说使用new关键字,反射以及clone方法。对比一下new和clone的区别,new一个对象的时候,首先会去检查该对象的class文件是否加载进入方法区,如果没有则先去加载class文件,然后分配一块空间给对象,之后再进行一系列的初始化,这样就在堆中得到了一个对象,而clone方法则是在根据一个对象中复制另一个新的对象。在有的场景中,我们可能需要一系列相同的对象,但是这些对象通过new创建的成本却很高,这时就可以调用clone方法,这在设计模式中的原型设计模式中得到了应用。同时有的时候我么也有复制对象的场景,但是通过引用赋值的方式,只能复制引用,不能复制堆中的对象。

    clone还有深拷贝和浅拷贝的区别。深拷贝指得是对象本身以及对象包含的引用指向的堆中对象都进行拷贝,浅拷贝则是引用进行了复制但没有真正拷贝引用所指向的对象。

原文地址:https://www.cnblogs.com/zeng-xian-hui/p/11219214.html

时间: 2024-10-06 13:52:58

jdk源码每日一读 (一) java.lang.Object的相关文章

JDK源码学习(9)- java.util.Properties实例与源码

java.util.Properties说明. 该类主要是读取属性配置文件,两种文件类型:普通文件格式为key = value:xml文件. 1)key = value示例如下: public class TestProperties { public static void main(String[] args) { Properties properties = new Properties(); FileInputStream fileInputStream; try { fileInpu

JDK源码学习(4)-java.util.HashMap、LinkedHashMap与TreeMap

一.HashMap 该类的节点Node类为: static class Node<K,V> implements Map.Entry<K,V> {         final int hash;         final K key;         V value;         Node<K,V> next;         Node(int hash, K key, V value, Node<K,V> next) {             th

【java基础之jdk源码】Object

最新在整体回归下java基础薄弱环节,以下为自己整理笔记,若有理解错误,请批评指正,谢谢. java.lang.Object为java所有类的基类,所以一般的类都可用重写或直接使用Object下方法,以下为逻辑结构图,没有画类图 (注: 以上绿色方法为 非native方法  粉色方法为 native方法) 那么问题来了 : 1.what is a native object? 本人理解: native关键字标识的java方法为本地方法,底层是有c/c++编写的程序编译后dll文件,java加载d

jdk源码阅读笔记之java集合框架(一)(基础篇)

结合<jdk源码>与<thinking in java>,对java集合框架做一些简要分析(本着实用主义,精简主义,遂只会挑出个人认为是高潮的部分). 先上一张java集合框架的简图: 会从以下几个方面来进行分析: java 数组; ArrayList,LinkedList与Vector; HashMap; HashSet 关于数组array: 数组的解释是:存储固定大小的同类型元素.由于是"固定大小",所以对于未知数目的元素存储就显得力不从心,遂有了集合.

从JDK源码角度看java并发的原子性如何保证

JDK源码中,在研究AQS框架时,会发现很多地方都使用了CAS操作,在并发实现中CAS操作必须具备原子性,而且是硬件级别的原子性,java被隔离在硬件之上,明显力不从心,这时为了能直接操作操作系统层面,肯定要通过用C++编写的native本地方法来扩展实现.JDK提供了一个类来满足CAS的要求,sun.misc.Unsafe,从名字上可以大概知道它用于执行低级别.不安全的操作,AQS就是使用此类完成硬件级别的原子操作. Unsafe是一个很强大的类,它可以分配内存.释放内存.可以定位对象某字段的

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

Java中集合框架,Collection接口、Set接口、List接口、Map接口,已经常用的它们的实现类,简单的JDK源码分析底层实现

(一)集合框架: Java语言的设计者对常用的数据结构和算法做了一些规范(接口)和实现(实现接口的类).所有抽象出来的数据结构和操作(算法)统称为集合框架. 程序员在具体应用的时候,不必考虑数据结构和算法实现细节,只需要用这些类创建一些对象,然后直接应用就可以了,这样就大大提高了编程效率. (二)集合框架包含的内容: (三)集合框架的接口(规范)   Collection接口:存储一组不唯一,无序的对象 List接口:存储一组不唯一,有序的对象 Set接口:存储一组唯一,无序的对象 Map接口:

JDK源码笔记-java.util.HashMap

HashMap 的存储实现 当程序试图将多个 key-value 放入 HashMap 中时,以如下代码片段为例: Java代码 HashMap<String , Double> map = new HashMap<String , Double>(); map.put("语文" , 80.0); map.put("数学" , 89.0); map.put("英语" , 78.2); HashMap 采用一种所谓的&quo

【JDK源码】JDK的java.util.concurrent包结构

本文从JDK源码包中截取出concurrent包的所有类,对该包整体结构进行一个概述. 在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便.而当针对高质量Java多线程并发程序设计时,为防止死蹦等现象的出现,比如使用java之前的wait().notify()和synchronized等,每每需要考虑性能.死锁.公平性.资源管理以及如何避免线程安全性方面带来的危害等诸多因素,往往会采