1.概述

原文:https://mp.weixin.qq.com/s?__biz=MzI4Njg5MDA5NA==&mid=2247484210&idx=1&sn=9d40e2e4c72f0727c7b7925cbe314fc0&chksm=ebd74233dca0cb2560677c7dc7746bf166195d793860c41ab477431af2cf0a6004477e27b814&scene=21#wechat_redirect

其实就可以归纳成几个:

registerNatives()【底层实现、不研究】
hashCode()
equals(Object obj)
clone()
toString()
notify()
notifyAll()
wait(long timeout)【还有重载了两个】
finalize()

Object一共有11个方法,其中一个为底层的实现registerNatives(),其中两个wait()和wait(long timeout, int nanos)重载方法。

所以我们真正需要看的就是8个方法

还有一个属性:

 /*** Returns the runtime class of this {@code Object}. The returned* {@code Class} object is the object that is locked by {@code* static synchronized} methods of the represented class.** <p><b>The actual result type is {@code Class<? extends |X|>}* where {@code |X|} is the erasure of the static type of the* expression on which {@code getClass} is called.</b> For* example, no cast is required in this code fragment:</p>** <p>* {@code Number n = 0;                             }<br>* {@code Class<? extends Number> c = n.getClass(); }* </p>** @return The {@code Class} object that represents the runtime*         class of this object.* @jls 15.8.2 Class Literals*/public final native Class<?> getClass();

equals和hashCode方法

quals和hashCode方法可以说是面试的重点题了,配合着String可以说在面试题中哪都有它们的存在。

首先,我们来看看equals和hashCode在Object中原生的实现吧:

hashCode:

public native int hashCode();

equals:

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

看上去都非常简单:

hashCode()由native方法底层实现了。equals()就直接==判断是否相等了。

想要更加清晰它们究竟是做什么的,我们来读读它的注释:


根据注释我们可以总结以下的要点:

  1. 重写equals()方法,就必须重写hashCode()的方法
  2. equals()方法默认是比较对象的地址,使用的是==等值运算符
  3. hashCode()方法对底层是散列表的对象有提升性能的功能
  4. 同一个对象(如果该对象没有被修改):那么重复调用hashCode()那么返回的int是相同的!
  5. hashCode()方法默认是由对象的地址转换而来的

equals()方法还有5个默认的原则:

  1. 自反性—>调用equals()返回的是true,无论这两个对象谁调用equals()都好,返回的都是true
  2. 一致性—>只要对象没有被修改,那么多次调用还是返回对应的结果!
  3. 传递性—>x.equals(y)和y.equals(z)都返回true,那么可以得出:x.equals(z)返回true
  4. 对称性—>x.equals(y)和y.equals(x)结果应该是相等的。
  5. 传入的参数为null,返回的是false

为啥说hashCode()以散列表为底层带来性能的提升是很容易理解的。我们再来回顾一下HashMap的插入:


如果hash值都不相等,那么可以直接判断该key是不相等的了!

equals和hashCode方法重写

equals()方法默认是比较对象的地址,使用的是==等值运算符。但是按我们正常开发来说,比较的是对象地址是没有意义的。

一般地,如果我们有两个Address对象,只要这两个对象的省号、城市号、街道号相等,我们就认为这两个对象相等了!

String实现的equals和hashCode方法

我们在初学的时候可能就听过了:String已经实现了equals和hashCode方法了。

这也就是为什么,我们可以直接使用String.equals()来判断两个字符串是否相等!

下面我们就来看看它的实现吧:

    /*** Returns a hash code for this string. The hash code for a* {@code String} object is computed as* <blockquote><pre>* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]* </pre></blockquote>* using {@code int} arithmetic, where {@code s[i]} is the* <i>i</i>th character of the string, {@code n} is the length of* the string, and {@code ^} indicates exponentiation.* (The hash value of the empty string is zero.)** @return  a hash code value for this object.*/public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}

toString方法

接下来我们看看toString方法,也十分简单:


toString方法主要是用来标识该对象的:

从上面的结果我们都可以看出来:得出的结果我们并不能看到什么东西~

于是我们一般都重写toString(),那么打印出的结果就很方便我们调试了!

  @Overridepublic String toString() {return "Address{" +"provinceNo=" + provinceNo +", cityNo=" + cityNo +", streetNo=" + streetNo +'}';}

下面的结果看起来就好多了:

clone方法

我们也来看看它的顶部注释:


看了上面的注释我们可以总结以下的要点:

clone方法用于对象的克隆,一般想要克隆出的对象是独立的(与原有的对象是分开的)

深拷贝指的是该对象的成员变量(如果是可变引用)都应该克隆一份,浅拷贝指的是成员变量没有被克隆一份

下面我们来看一下浅拷贝:拷贝了Employee对象,但是其成员变量hireday没有被克隆出去,所以指向的还是同一个Date对象!

clone用法

那么我们如何克隆对象呢?无论是浅拷贝还是深拷贝都是这两步:

  1. 克隆的对象要实现Cloneable接口
  2. 重写clone方法,最好修饰成public

浅拷贝:仅仅拷贝了Person对象,而date没有拷贝!

public class Person implements Cloneable {// 可变的成员变量private Date date;@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}}

深拷贝:不仅拷贝了Person对象,也拷贝了date成员变量

public class Person implements Cloneable {// 可变的成员变量public  Date date;@Overridepublic Object clone() throws CloneNotSupportedException {// 拷贝Person对象Person person = (Person) super.clone();// 将可变的成员变量也拷贝person.date = (Date) date.clone();// 返回拷贝的对象return person;}}

4.2 clone疑问进一步学习protected

不知道有没有人跟我有相同的疑问:

我只想要浅拷贝,能不能直接调用该对象.clone()来实现?

比如我现在有个Address对象:

public class Address  {private int provinceNo;private int cityNo;private int streetNo;public Address() {}public Address(int provinceNo, int cityNo, int streetNo) {this.provinceNo = provinceNo;this.cityNo = cityNo;this.streetNo = streetNo;}
}

下面的代码你们认为如何?

Address address = new Address(1, 2, 3);address.clone();

我们都知道:

protected修饰的类和属性,对于自己、本包和其子类可见

可能会想:clone()方法是定义在Object类上的(以protected来修饰),而我们自定义的Address对象隐式继承着Object(所有的对象都是Object的子类),那么子类调用Object以protected来修饰clone()是完全没问题的

但是,IDE现实告诉我,这编译就不通过了!


出现错误的原因我立马就想到:是不是我对protected修饰符出现了偏差?

protected修饰的类和属性,对于自己、本包和其子类可见,这句话本身是没有错的。但是还需要补充:对于protected的成员或方法,要分子类和超类是否在同一个包中。与基类不在同一个包中的子类,只能访问自身从基类继承而来的受保护成员,而不能访问基类实例本身的受保护成员。

上面的代码就错在:Address与Object不是在同一个包下的,而Address直接访问了Object的clone方法。这是不行的。

下面我截两张图再来给你们看看(看完图再看上面的描述,就能理解了):

五、wait和notify方法

wait和notify方法其实就是Java给我们提供让线程之间通信的API。

按照惯例我们还是来看注释怎么说吧:

wait方法:

notify方法:

notifyAll()方法:

看完上面的注释我们可以总结以下的要点:

  1. 无论是wait、notify还是notifyAll()都需要由监听器对象(锁对象)来进行调用

    1. 简单来说:他们都是在同步代码块中调用的,否则会抛出异常!
  2. notify()唤醒的是在等待队列的某个线程(不确定会唤醒哪个),notifyAll()唤醒的是等待队列所有线程
  3. 导致wait()的线程被唤醒可以有4种情况
    1. 该线程被中断
    2. wait()时间到了
    3. 被notify()唤醒
    4. 被notifyAll()唤醒
  4. 调用wait()的线程会释放掉锁

其实总结完上面的并不会有比较深刻的印象,可以尝试着回答几个问题来加深对wait()和notify()的理解。

为什么wait和notify在Object方法上?

从一开始我们就说了:wait()和notify()是Java给我们提供线程之间通信的API,既然是线程的东西,那什么是在Object类上定义,而不是在Thread类上定义呢?

因为我们的锁是对象锁【要是忘记的同学可回顾:Java锁机制了解一下】,每个对象都可以成为锁。让当前线程等待某个对象的锁,当然应该通过这个对象来操作了。

锁对象是任意的,所以这些方法必须定义在Object类中

notify方法调用后,会发生什么?

上面已经说了,notify会唤醒某个处于等待队列的线程。

但是要注意的是:

notify方法调用后,被唤醒的线程不会立马获得到锁对象。而是等待notify的synchronized代码块执行完之后才会获得锁对象

sleep和wait有什么区别?

Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权。

主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。
而Thread.sleep()没有对锁释放

参考资料:

https://blog.csdn.net/lingzhm/article/details/44940823

http://www.cnblogs.com/dolphin0520/p/3920385.html

https://www.cnblogs.com/eer123/p/7880789.html

https://www.jianshu.com/p/f4454164c017

【Java】Java 的Object对象你真的懂了吗相关推荐

  1. java中判断Object对象类型

    记录一下 Object param = params.get(i);if (param instanceof Integer) {int value = ((Integer) param).intVa ...

  2. java初始化实例化_Java对象的创建过程:类的初始化与实例化

    一.Java对象创建时机 我们知道,一个对象在可以被使用之前必须要被正确地实例化.在Java代码中,有很多行为可以引起对象的创建,最为直观的一种就是使用new关键字来调用一个类的构造函数显式地创建对象 ...

  3. java反射 获取Object属性值

    项目场景: 一个添加员工信息的功能,通过shiro获取当前登录用户的信息,取出其中的createId的值,在通过set方法写入. 问题描述: 通过获取的登录用户的信息发现,它是一个Object对象,然 ...

  4. JVM系列之:详解java object对象在heap中的结构

    文章目录 简介 对象和其隐藏的秘密 Object对象头 数组对象头 整个对象的结构 简介 在之前的文章中,我们介绍了使用JOL这一神器来解析java类或者java实例在内存中占用的空间地址. 今天,我 ...

  5. 面试官问你Java线程池--怎么样回答才能让面试官知道你真的懂了!

    一.引言 不管是Java面试还是Android面试,线程池都是面试官高频考察的点,那我们怎么回答,才能让面试官了解到我们是真的懂Java线程池了呢?这篇文章不涉及到线程池的使用和原理,如果你还不知道怎 ...

  6. java object大小_在Java中,确定对象object大小的最佳方法是什么? - Break易站

    例如,假设我有一个应用程序,它可以读取包含一堆数据行的CSV文件.我根据数据类型向用户提供行数摘要,但是我想确保不读取太多数据行并导致OutOfMemoryErrors.每一行都会翻译成一个对象.有没 ...

  7. Java是什么?你真的懂Java吗?

    关于Java,我想知道的 1.java是什么? 2.java能用来干嘛? 3.为什么要学习 Java 4. Java 有哪些特点 5.那新手如何学习JAVA呢? 1.java是什么? Java是一种开 ...

  8. Synchronized结合Java Object对象中的 wait,notify,notifyAll

    前面我们在讲synchronized的时候,发现被阻塞的线程什么时候被唤醒,取决于获得锁的线程什么时候执行完同步代码块并且释放锁.那怎么做到显示控制呢?我们就需要借助一个信号机制: 在Object对象 ...

  9. jquery 遍历java对象_jquery中object对象循环遍历的方法

    一个朋友问对象如何转为数组,当我问他为啥要转得时候,他告诉我,数组可以用js循环遍历,而对象则不可以.其实呢,对象同样可以循环遍历的啊.不用转换也可以循环!说明你对js或者jquery的某些操作不是很 ...

最新文章

  1. layui栅格布局问题
  2. CentOS6.5下编译R源码并安装Spark R
  3. Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
  4. Mybatis使用之 Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias‘User’
  5. myeclipse 2017 CI 中如何修改Servlet模板
  6. mysql-libs 5.6.23_利用rpm包手把手教你安装MySQL5.6.23
  7. Creative Groove Randomizer插件:Audiomodern Playbeat节拍生成器
  8. 解题报告——-2018级2016第二学期第三周作业
  9. 国产cpu芯片架构和指令集
  10. 数学之美--读书笔记
  11. 新浪微博开放平台提交审核时Android签名生成
  12. CentOS 7 时区设置
  13. 【洛谷P4315】月下毛景树 树链剖分03
  14. 数字绕圈算法 JS 实现
  15. 浏览器输入一个URL地址后发生的事情
  16. 一元稀疏多项式加减法计算器
  17. ansible架构、安装、简单的使用
  18. “零”代码改动,静态编译让太乙Stable Diffusion推理速度翻倍
  19. 四川发展供应链金融的三个建议及对策
  20. 紫光同创国产FPGA学习之Timing Analyzer

热门文章

  1. 快手通过港交所聆讯 2020年前三季度经调亏损72亿元
  2. 灯塔上线网络电影日分账票房数据,网络电影进入票房日更时代
  3. 联姻寺库,一次半斤八两的合作,趣店的奢侈品生意仍看不见未来
  4. 微信号都可以改了,那淘宝号呢?官方硬核回应遭网友吐槽:你没有心!
  5. 裁员之后人手却不够,马斯克和母亲只好亲自上阵帮忙了
  6. 曾经很火但消失了的软件,你还记得几个?
  7. 罗永浩又提西门子:希望网友帮介绍西门子管理层
  8. iPhone XS Max第三方售价低于7千元 引用户疯抢
  9. 专访iQOO Pro产品经理:以更好的产品 更低的价格推进5G生态普及
  10. 中国移动自主品牌首款5G手机亮相!越看越有华为的影子?