一. Object

少年你有没有发现,在你使用心爱的idea快捷创建对象时,Alt+Ins后弹出来的选项除了你常用的构造方法和getset方法,还有其他我们最常用的方法equals, hashCode以及toString

java打印map对象_引用数据类型

 其中这三个方法都隶属于Object类,下面我们就来了解Object

1.定义

Object 是类层次结构的根,每个类都可以将 Object 作为超类

也就是说所有类都直接或者间接继承于Object类;换句话说,该类所具备的方法,其他所有类都继承了,其他类都可以重写其中的方法

java打印map对象_引用数据类型_02

 

2.常见方法

打开java API文档,我们可以看到Object的全部方法

java打印map对象_引用数据类型_03

其中我们只需先了解下面三个方法,其余方法多用于多线程

⑴toString

toString:返回该对象的字符串表示

①源码

如图:我创建了一个Student对象s,并输出打印了s. toString

java打印map对象_java_04

下面我们定位到toString的源码 

java打印map对象_引用数据类型_05

其中调用的方法是什么我们不需要了解,我们只需要知道每一部分的含义,其中返回的字符串我们称之为对象的内存地址值

当然获取对象的内存地址值没有太大的意义,

获取对象的成员变量的字符串拼接形式才算有意义,那么我们就需要在对象中重写toString方法

如图:重写toString方法输出打印s,此时我们就可以清楚的看到Student的成员变量值

java打印map对象_引用数据类型_06

因此重写toString方法的意义就是

方便的展示对象中的属性值

⑵equals

equals:指示其他某个对象是否与此对象"相等"

①源码

我们在比较引用数据类型时(如int)使用的是"==",比较引用数据类型时(比如String),使用的一般都是equals,那我可不可以引用数据类型也用"=="? equals的底层是用什么比较的?

如图:打开Object中equals的源码,我们发现,equals的底层比较居然也是用"=="比较的!

java打印map对象_java_07

好!那我创建两个Student对象,来比较一下看他们是否相等

如图:我创建了两个对象,变量都赋值为"张三",我想要比较他俩的属性是否相等

java打印map对象_引用数据类型_08

运行发现,诶?俩属性值都是"张三",怎么比较结果是false?那我们来打印一下他们的值

如图:打印发现打印的是地址值

java打印map对象_java_09

因此引用数据类型"=="比较的是地址值

那我想要比较对象的属性值,就要重写equals方法 

java打印map对象_java_10

 

接下来我们来看Objects中的equals方法

java打印map对象_java_11

发现Objects中的equals方法比Object中的equals方法多了一个调用者的非空判断 

⑶hashCode

hashCode:返回该对象的哈希码值

什么是哈希码值?

哈希码值就是对象的整数表现形式,哈希表就是根据键的哈希值来进行去重的

要注意的是

①如果没有重写hashCode方法,不同对象的哈希值就不同

因为Objects中的哈希值是根据对象的地址值计算的,不同对象的地址值不同,哈希值也就不同,也就无法进行去重

②重写方法后,对象的属性值相同哈希值就相同

重写后的hashCode方法底层调用的是Arrays中的hashCode,下面我们来看看源码

如图:在JavaBean中重写的hashCode方法将对象的属性值传入

java打印map对象_多线程_12

数组a就是属性值,在hashCode中根据属性值计算哈希值并返回 

java打印map对象_属性值_13

③哈希碰撞

哈希碰撞就是不同的哈希值计算可能出现哈希值相等的情况

3.小结

⑴输出对象的地址值一般没有意义,我们可以通过重写toString方法去输出对应的成员变量信息

注:一般情况下Jdk所提供的类都会重写Object类中的toString方法,如ArrayList

⑵比较对象的地址值是没有意义的,因此一般情况下我们都会重写Object类中的equals方法以此来比较对象的属性值

⑶不同对象的哈希值不同,若要进行对象的去重,就要重写hashCode方法

二.多线程协作中的Object

前面我们了解了Object中最基础的三个方法,下面我们就来看看在多线程协作中最常用的两个方法wait和notify

1.生产者和消费者模式

生产者和消费者模式是一个十分经典的多线程协作的模式,又叫做等待唤醒机制,打破了线程的随机机制,让多个线程轮流执行

⑴生产者和消费者的逻辑

我们可以把生产者比作厨师,消费者比作顾客,厨师做好食物放到桌子上,顾客看到桌子上的食物就吃

当生产者进入时,若发现桌子上有食物,那么它就会沉睡等待,若发现桌子上没有食物,那么它就会生产并叫醒消费者

java打印map对象_属性值_14

当消费者进入时,若发现桌子上没有食物,那么它就会沉睡等待;若发现桌子上有食物,那么它就会消费并叫醒生产者

java打印map对象_java_15

⑵wait和notify

wait在此模式下就是沉睡线程,notify在此模式下就是唤醒线程

java打印map对象_java_16

java打印map对象_多线程_17

注: wait和notify必须在同步代码块或同步方法中使用