作为所有类的顶层父类,没想到Object的魔力如此之大!

这篇具有很好参考价值的文章主要介绍了作为所有类的顶层父类,没想到Object的魔力如此之大!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在开头

在上一篇博文中我们提到了Java面向对象的四大特性,其中谈及“抽象”特性时做了一个引子,引出今天的主人公Object,作为所有类的顶级父类,Object被视为是James.Gosling的哲学思考,它高度概括了事务的自然与社会行为。

源码分析

跟进Object类的源码中我们可以看到,类的注释中对它做了一个总结性的注释。
作为所有类的顶层父类,没想到Object的魔力如此之大!

在Object的内部主要提供了这样的11种方法,大家可以在源码中一个个的跟进去看,每个方法上均有详细的英文注释,养成良好的看英文注释习惯,是一个合格程序员的必备基础技能哈。

/**
 * 方法一
 */
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 { }

getClass()

getClass()是Java的一个native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。在源码中我们可以到,该方法的返回是Class类。
Class 类存放类的结构信息,能够通过 Class 对象的方法取出相应信息:类的名字、属性、方法、构造方法、父类、接口和注解等信息。

hashCode()

同样是native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。

equals()

默认比较对象的地址值是否相等,子类可以重写比较规则,如String 类对该方法进行了重写以用于比较字符串的值是否相等。

clone()

native 方法,用于创建并返回当前对象的一份拷贝。

toString()

返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。

notify()

native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。

notifyAll()

native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。

wait(long timeout)

native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。

wait(long timeout, int nanos)

多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。

wait()

让持有对象锁的线程进入等待,不可设置超时时间,没有被唤醒的情况下,会一直等待。

finalize()

实例被垃圾回收器回收的时候触发的操作

高频面试考点总结

虽然在日常的代码开发中,我们很少会直接使用Object类,但考虑到它的独特地位,与此相关的面试考点还是不少的,我们今天总结一下。

1.浅拷贝、深拷贝、引用拷贝的区别?

浅拷贝:基本类型的属性会直接复制一份,而引用类型的属性复制:复制栈中的变量和变量指向堆内存中的对象的指针,不复制堆内存中的对象,也就是说拷贝对象和原对象共用同一个内部对象。
作为所有类的顶层父类,没想到Object的魔力如此之大!

深拷贝:深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。
作为所有类的顶层父类,没想到Object的魔力如此之大!

引用拷贝:简单来说,引用拷贝就是两个不同的引用指向同一个对象。
作为所有类的顶层父类,没想到Object的魔力如此之大!

2.Java中如何实现浅拷贝与深拷贝

其实实现浅拷贝很简单,实现 Cloneable 接口,重写 clone() 方法,在clone()方法中调用父类Object的clone()方法。

public class TestClone {
 
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1 = new Person(1, "ConstXiong");//创建对象 Person p1
        Person p2 = (Person)p1.clone();//克隆对象 p1
        p2.setName("其不答");//修改 p2的name属性,p1的name未变
        System.out.println(p1);
        System.out.println(p2);
    }
    
}
 
/**
 * person类
 */
class Person implements Cloneable {
    
    private int pid;
    
    private String name;
    
    public Person(int pid, String name) {
        this.pid = pid;
        this.name = name;
        System.out.println("Person constructor call");
    }
 
    public int getPid() {
        return pid;
    }
 
    public void setPid(int pid) {
        this.pid = pid;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    @Override
    public String toString() {
        return "Person [pid:"+pid+", name:"+name+"]";
    }
    
}

那么如何实现深拷贝呢,这里给出两种方法
方法一:将对象的属性的Class 也实现 Cloneable 接口,在克隆对象时也手动克隆属性。
方法二:结合序列化(JDK java.io.Serializable 接口、JSON格式、XML格式等),完成深拷贝。

3.==和equals的区别是什么?

**区别**
== 是关系运算符,equals() 是方法,结果都返回布尔值
Object 的 == 和 equals() 比较的都是地址,作用相同

**== 作用:**
基本类型,比较值是否相等
引用类型,比较内存地址值是否相等
不能比较没有父子关系的两个对象

**equals()方法的作用:**
JDK 中的类一般已经重写了 equals(),比较的是内容
自定义类如果没有重写 equals(),将调用父类(默认 Object 类)的 equals() 方法,Object 的 equals() 比较使用了 this == obj
可以按照需求逻辑,重写对象的 equals() 方法(重写 equals 方法,一般须重写 hashCode 方法)

4.为什么说重写equals方法也要重写hashCode方法呢?

equals()方法是用来判断两个对象是否相等的重要方法,Object中默认比较地址,但这在实际使用上意义不大,比如两个字符串,我们比较的初衷肯定是他们的字符串内容是否相等,而不是内存地址,典型的就是String内部的重写equals。

hashCode()方法是一个C或C++实现的本地方法,用以获取对象的哈希码值(散列码),通过码值可以确定该对象在哈希表中的索引位置,是通过线程局部状态来实现的随机数值。子类可通过重写该方法去重新设计hash值。
使用hashCode方法可以一定程度上判断两个对象是否相等,因为,若两个对象相等,那么他们所在的索引位置肯定就一样,这时hashCode获取的哈希码自然也就一样,但这个条件反过来就不一定成立了,哈希码相等的两个对象不一定相等,因为存在哈希碰撞

看完这两个方法的特点,我们大概可以明白了,确保两个对象是否真正相等,需要这个两个方法的协作,equals是逻辑上的相等,hashCode是物理上的相等,若我们在重写equals()方法时,不去重写配套的hashCode方法,就会导致两个对象在逻辑上相等,但物理上不等,这会带来很多问题,譬如集合类HashMap的底层实现是数据+链表/红黑树的方式,通过计算hash寻找位置,通过equals判断元素相等,这时候若仅重写equals的话,hash不重写,就会出现逻辑上我们认为相等的两个数,存在了不同的位置上,造成混乱的场面。文章来源地址https://www.toymoban.com/news/detail-788587.html

到了这里,关于作为所有类的顶层父类,没想到Object的魔力如此之大!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 没想到还有这种骚操作~如何使用Golang实现无头浏览器截图?

    在Web开发中,有时需要对网页进行截图,以便进行页面预览、测试等操作。 而使用无头浏览器来实现截图功能,可以避免手动操作的繁琐和不稳定性。 这篇文章将介绍: 使用Golang进行无头浏览器的截图,轻松实现页面预览、测试和模拟用户操作。 这篇文章发完,有朋友在朋

    2024年02月05日
    浏览(49)
  • 真没想到啊!无需服务器,五分钟部署公众号机器人

    大家好,我是编程哥。一个寻求破圈,不断淬炼自己的人,关注我一起进步。 目前各大模型都比较火,作为一名程序员,对大模型的了解也是蠢蠢欲动,尤其是对于机器人自动问答这一项。所以在朋友的推荐下,了解了一个无需服务器,快速搭建公众号机器人的教程,现在分

    2024年02月03日
    浏览(37)
  • 没想到,JDBC 驱动会偷偷修改 sql_mode 的会话值

    最近碰到一个 case,值得分享一下。 现象就是一个 update 操作,在 mysql 客户端中执行提示 warning,但在 java 程序中执行却又报错。 update 语句中使用 STR_TO_DATE 函数将字符串转换为日期时间格式。 但因为这个格式字符串 \\\'%Y-%m-%d %H:%i:%s\\\' 没有对日期字符串中的毫秒部分 .0 进行解析

    2024年03月09日
    浏览(40)
  • 5年测试经验怎么着我也能要个20K吧?没想到被阿里P8问傻了

    都说金三银四是跳槽涨薪季,我也是着急忙慌的准备简历—— 5年软件测试经验,可独立测试大型产品项目,熟悉项目测试流程…薪资要求?5年测试经验起码能要个20K吧? 我加班肝了一页半简历,投出去一周,面试电话倒是不少,自信满满去面试,现场被问了这么几个问题—

    2024年02月08日
    浏览(45)
  • 5年测试经验怎么着我也能要个20K吧?没想到被阿里P8问傻了····

    都说金三银四是跳槽涨薪季,我也是着急忙慌的准备简历—— 5年软件测试经验,可独立测试大型产品项目,熟悉项目测试流程…薪资要求?5年测试经验起码能要个20K吧? 我加班肝了一页半简历,投出去一周,面试电话倒是不少,自信满满去面试,现场被问了这么几个问题—

    2024年02月08日
    浏览(41)
  • [链表OJ题 8] 用栈实现队列,没想到你小子的基础这么好,这么快就做对了

    目录 题目来源: 代码实现: 思路分析: 实现过程: 力扣 - 232.用栈实现队列 题目描述: 我们这里的栈已经写好了,如果对栈还不是很懂的可以看看这篇文章:CSDN - [数据结构 -- C语言] 栈(stack) 我们知道 队列的特性:先入先出;栈的特性:先入后出。 因此我们定义两个栈

    2024年02月06日
    浏览(74)
  • 云安全_什么是云,云计算的本质,没想到一个Handler还有中高级几种问法

    是将计算机终端系统进行虚拟化,以达到桌面使用的安全性和灵活性。可以通过任何设备,在任何地点,任何时间通过网络访问属于我们个人的桌面系统。 存储虚拟化 是对存储硬件资源进行抽象化表现。 网络虚拟化 网络虚拟化就是在一个物理网络上模拟出多个逻辑网络来。

    2024年04月13日
    浏览(43)
  • [Lua] 实现所有类的基类Object、模拟单继承OO、实现抽象工厂

    Lua 没有严格的 oo(Object-Oriented)定义,可以利用元表特性来实现 先定义所有类的基类,即 Object 类。代码顺序从上到下,自成一体。完整代码 定义一个空表 Object , __index 指向其自身(继承将直接使用该表作为对象的元表) new 定义构造对象时的初始化行为,相当于 构造器

    2024年02月11日
    浏览(36)
  • Python中的super:调用父类的构造方法

     在子类构造方法中调用父类构造方法的两种方式: 1、未绑定的方法: 直接使用父类名来进行调用 ,即‘父类名.父类方法名(self,[参数1, 参数2,...])’ 2、 super() : 如果涉及多继承,该函数只能调用第一个直接父类的构造方法。super().父类方法名(self, [参数1, 参数2,...])或supe

    2024年02月15日
    浏览(57)
  • 【iOS开发】理解OC的类,父类,元类的关系

    在OC中,有对象objc,有类Class,有父类SuperClass,其实还有一种元类MetaClass。在接下来的RunLoop,消息转发机制的学习之前需要知道OC类和对象的底层,所以理解类, 父类,元类的关系是基础 在 Objective-C 中,类是对象的模板或蓝图,而对象则是类的实例。每个对象都有一个类作

    2024年02月03日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包