作为所有类的顶层父类,没想到Object的魔力如此之大!
写在开头
在上一篇博文中我们提到了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的魔力如此之大!的更多相关文章
- 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题…..
1.类加载过程 类加载时机 「加载」 将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存上创建一个java.lang.Class对象用来封装类在方法区内的数据 ...
- Android(java)学习笔记119:继承中父类没有无参构造
/* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢? 报错. 如何解决呢? A:在父类中加一个无参构造方法 B:通过使用super关键字去显示的调用父类的带参构造方法 C:子类通过th ...
- 【JVM虚拟机】(6)---深入理解Class中访问标志、类索引、父类索引、接口索引
JVM(6)访问标志,类索引 上一篇博客讲[JVM虚拟机](5)---深入理解JVM-Class中常量池 我们知道一个class文件正常可以分为7个部分: 魔数与class文件版本 常量池 访问标志 ...
- 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来
在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...
- Android(java)学习笔记60:继承中父类 没有无参构造
1. 继承中父类 没有无参构造: package com.himi.test1; /* 如果父类没有无参构造方法,那么子类的构造方法会出现什么现象呢? 报错. 如何解决呢? A:在父类中加一个无参构造 ...
- mybatis-plus代码生成,实体类不生成父类属性
一.参考文档: 官方文档其实说的很清楚了,可能有个别地方有点不太清楚. mybatis-plus官方: https://mp.baomidou.com/guide/generator.html 模版引 ...
- 杀死众筹的N种方法:没想到山寨大军也参与了
众筹作为当下创业者筹集资金,将创意变为现实的最重要手段之一,正面临着越来越多的困难,甚至衍生出杀死众筹的N种方法.甚至这些方法还分为了两类,就众筹本身看,杀死它们的主要方法是:创业者卷钱跑路. ...
- 没想到 Google 排名第一的编程语言,为什么会这么火?
没想到吧,Python 又拿第一了! 在 Google 公布的编程语言流行指数中,Python 依旧是全球范围内最受欢迎的技术语言! 01 为什么 Python 会这么火? 核心还是因为企业需要用 ...
- 没想到吧!这个可可爱爱的游戏居然是用 ECharts 实现的!
摘要:echarts 是一个很强大的图表库,除了我们常见的图表功能,还可以自定义图形,这个功能让我们可以很简单地在画布上绘制一些非常规的图形,基于此,我们来玩一些花哨的:做一个 Flappy Bird ...
- JVM-class文件完全解析-类索引,父类索引和索引集合
类索引,父类索引和接口索引集合 前面介绍了class文件,从头开始的魔数,次版本号,主版本号,常量池入口,常量池,访问标志.那么再接下来的就是用来确定这个类的继承关系的类索引,父类索引和接口索引集合这 ...
随机推荐
- HBuilderX内置终端无法使用不能输入
找到HBuilderX的目录打开plugins\builtincef3terminal\script找到main.js用记事本或其他什么打开他 把这部分代码替换成这个再重启hbuilderX就可以了 ...
- 使用PasteSpider把你的代码升级到服务器的Docker/Podman上,K8S太庞大,PasteSpider极易上手!
如果你的服务器的内存小于16GB,那么K8S就和你无缘了,但是你可以使用PasteSpider来实现发布你的项目到服务器上! PasteSpider是一个运维工具,使用NET编写的,部署于服务器的Do ...
- 2023年SWPU NSS 秋季招新赛 (校外赛道)WP—Crypto
一.Caesar_base 题目信息 s = "HIJKLMNOPQRSTUVWXYZABCDEFGhijklmnopqrstuvwxyzabcdefg0123456789+/" ...
- aspnetcore微服务之间grpc通信,无proto文件
aspnetcore微服务之间通信grpc,一般服务对外接口用restful架构,HTTP请求,服务之间的通信grpc多走内网. 以前写过一篇grpc和web前端之间的通讯,代码如下: exercis ...
- 简单实现.NET Hook与事件模拟
最近玩<星露谷物语>上瘾,本来是看着个休闲游戏,现在玩成修仙游戏了,上百个小时浑身是肝,中午午休习惯都强行给改了. 虽然挺有意思,但是太肝了,入坑前请谨慎.补充一下,这个游戏应该是基于 X ...
- RLChina2022-实践课三:强化学习算法
MDP算法 MDP被定义为一个元组(S,A,P,r,R) S:所有状态集合 A:在环境力里面智能体所作动作的集合 P:状态转移函数P(s'|s,a),智能体在当前s下,执行a之后,转移到是s'的概率 ...
- UML类图(最重要的三个关系)
关联关系 ============= 关联关系:B是A的属性(A contains B),则A-->B:另外的: 都是特殊的关联关系 AB: 聚合(Aggregation)关系表示整体与部分的关 ...
- 从零实现的浏览器Web脚本
从零实现的浏览器Web脚本 在之前我们介绍了从零实现Chrome扩展,而实际上浏览器级别的扩展整体架构非常复杂,尽管当前有统一规范但不同浏览器的具体实现不尽相同,并且成为开发者并上架Chrome应用商 ...
- CSS 浮动和清除浮动方法总结
作者:WangMin 格言:努力做好自己喜欢的每一件事 什么是浮动 float? 标准流:盒子会各占整行位置.子盒子若是标准流,父盒子虽然没有高度,但是会撑开父盒子高度. 浮动:盒子浮了起来,不会占据 ...
- 递归+DP:爬楼梯问题
一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级.求该青蛙跳上一个n 级的台阶总共有多少种跳法. 输入格式: 首先输入数字n,代表接下来有n组输入,50>=n>=0,然后每行一个 ...