写在开头

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

源码分析

跟进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.浅拷贝、深拷贝、引用拷贝的区别?

浅拷贝:基本类型的属性会直接复制一份,而引用类型的属性复制:复制栈中的变量和变量指向堆内存中的对象的指针,不复制堆内存中的对象,也就是说拷贝对象和原对象共用同一个内部对象。

深拷贝:深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。

引用拷贝:简单来说,引用拷贝就是两个不同的引用指向同一个对象。

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不重写,就会出现逻辑上我们认为相等的两个数,存在了不同的位置上,造成混乱的场面。

作为所有类的顶层父类,没想到Object的魔力如此之大!的更多相关文章

  1. 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题…..

    1.类加载过程 类加载时机 「加载」 将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存上创建一个java.lang.Class对象用来封装类在方法区内的数据 ...

  2. Android(java)学习笔记119:继承中父类没有无参构造

    /* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢? 报错. 如何解决呢? A:在父类中加一个无参构造方法 B:通过使用super关键字去显示的调用父类的带参构造方法 C:子类通过th ...

  3. 【JVM虚拟机】(6)---深入理解Class中访问标志、类索引、父类索引、接口索引

    JVM(6)访问标志,类索引 上一篇博客讲[JVM虚拟机](5)---深入理解JVM-Class中常量池 我们知道一个class文件正常可以分为7个部分: 魔数与class文件版本 常量池 访问标志 ...

  4. 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来

    在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...

  5. Android(java)学习笔记60:继承中父类 没有无参构造

    1. 继承中父类 没有无参构造: package com.himi.test1; /* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢? 报错. 如何解决呢? A:在父类中加一个无参构造 ...

  6. mybatis-plus代码生成,实体类不生成父类属性

    一.参考文档: 官方文档其实说的很清楚了,可能有个别地方有点不太清楚. mybatis-plus官方: https://mp.baomidou.com/guide/generator.html 模版引 ...

  7. 杀死众筹的N种方法:没想到山寨大军也参与了

    ​ ​ 众筹作为当下创业者筹集资金,将创意变为现实的最重要手段之一,正面临着越来越多的困难,甚至衍生出杀死众筹的N种方法.甚至这些方法还分为了两类,就众筹本身看,杀死它们的主要方法是:创业者卷钱跑路. ...

  8. 没想到 Google 排名第一的编程语言,为什么会这么火?

    没想到吧,Python 又拿第一了! 在 Google 公布的编程语言流行指数中,Python 依旧是全球范围内最受欢迎的技术语言!   01 为什么 Python 会这么火? 核心还是因为企业需要用 ...

  9. 没想到吧!这个可可爱爱的游戏居然是用 ECharts 实现的!

    摘要:echarts 是一个很强大的图表库,除了我们常见的图表功能,还可以自定义图形,这个功能让我们可以很简单地在画布上绘制一些非常规的图形,基于此,我们来玩一些花哨的:做一个 Flappy Bird ...

  10. JVM-class文件完全解析-类索引,父类索引和索引集合

    类索引,父类索引和接口索引集合 前面介绍了class文件,从头开始的魔数,次版本号,主版本号,常量池入口,常量池,访问标志.那么再接下来的就是用来确定这个类的继承关系的类索引,父类索引和接口索引集合这 ...

随机推荐

  1. 教学法学期末考试MOOC01

    期末考试 返回 期末考试试卷为客观题,总分为100分,占课程成绩的40%.其中包含16道单选题,2道多选题.共18道题.单选题每道5分,多选题每道10分,限时90分钟完成.  倒计时: 01:13:4 ...

  2. 创业团队建设与管理mooc【第二次中期测验】

    mo'o 第二次中期测验 返回 已经超过规定的测试次数或提交截止时间已过.你可以作为自我学习进行测验,但提交的结果将无法获得学分. 1 单选(2分) PDCA循环中的P是指什么? 得分/总分 A. 处 ...

  3. 在 Linux 环境(Ubuntu)下安装 Slurm 和 OpenMPI

    安装 Slurm 从软件源安装 slurm-wlm(每个节点都需要装的执行工具).slurm-client(客户机装的提交命令的工具).munge(节点间通信插件) sudo apt install ...

  4. vcpkg manifest 的使用

    最近项目上要使用 CMakeLists 管理,由于 Windows 版本有依赖到 vcpkg 提供的库,所以需要使用 vcpkg manifest 来统一设置库的版本,方便后续维护 推荐一个文章,介绍 ...

  5. 秋招过半零Offer怎么办?

    参加今年秋招的同学都知道,尤其是双非本科更是体验深刻.9 月份至今,面试寥寥无几.笔试也不是很多,大中小公司 Offer 没拿下一个.作为应届生的我们,该怎么办呢? 1.调整好心态 这个世界上有两种事 ...

  6. 由mysql转为oracle注意事项

    1. text类型->nclob 2. 表名是关键字   引号 3. 字段名是关键字 引号 4. 日期型和mysql不同,hh24:mi:ss  就是HH:mm:ss,库里存日期型也可以(查询时 ...

  7. 栩栩如生,音色克隆,Bert-vits2文字转语音打造鬼畜视频实践(Python3.10)

    诸公可知目前最牛逼的TTS免费开源项目是哪一个?没错,是Bert-vits2,没有之一.它是在本来已经极其强大的Vits项目中融入了Bert大模型,基本上解决了VITS的语气韵律问题,在效果非常出色的 ...

  8. CF1610B [Kalindrome Array]

    Problem 题目简述 给你一个数列 \(a\),有这两种情况,这个数列是「可爱的」. 它本身就是回文的. 定义变量 \(x\),满足:序列 \(a\) 中所有值等于 \(x\) 的元素删除之后,它 ...

  9. JavaScript:对象的三个属性

    每一个对象都有与之相关的原型(prototype).类(class)和可扩展性(extension attribute). 原型 prototype 对象的原型属性是用来继承属性的.通过对象直接量创建 ...

  10. 花了三年时间开发的开源项目,终于500 个 Star 了!

    waynboot-mall 商城项目从疫情开始初期着手准备,到现在已经经过了 3 年多的时间,从项目初期到现在,一个人持续迭代,修复漏洞,添加功能,经历了前端开发工具从 vue2.vue-cli 切换 ...