API篇(Java - 祖宗类(Object))(doing)

目录

一、简介

二、源码分析

三、常用方法

1. clone()

1.1. 作用

1.2. clone源码分析

1.3. Java的浅克隆与深克隆

浅克隆

深克隆

2. hashCode()

2.1. 简介

2.2. hash值

2.3. 案例

3. equals(obj)

3.1. 简介

3.2. 使用原则

3.3. 基本特性

3.4. 案例

4. getClass()

4.1. 简介

4.2. 案例

5. toString()

5.1. 简介

5.2. 案例

6. wait()、wait(long)、wait(long,int)、notify()、notifyAll()

7. finalize()

7.1. 简介

7.2. 案例

四、总结


一、简介

Java是面向对象的编程语言,而在面向对象中,所有的Java类都有一个共同的祖先类,这就是Object。

二、源码分析

在了解Object中的常用方法之前,我们先来看看Object类的源码,如下所示:

从Object类的源码注释可以知道,Object类是Java中所有类的父类,相当于是Java中的”万类之王“,处于最顶

层。所以在Java中,所有的类默认都继承自Object类。同时Java中的所有类对象,包括数组,也都要实现这个类

中的方法。

所以,Object是Java中所有类的父类、超类、基类,位于继承树的最顶层。

可以说,任何一个没有显式地继承别的父类的类,都会直接继承Object,否则就是间接地继承Object,并且任何

一个类也都会享有Object提供的方法。又因为Object是所有类的父类,所以基于多态的特性,该类可以用来代表

任何一个类,允许把任何类型的对象赋给 Object类型的变量,也可以作为方法的参数、方法的返回值。

三、常用方法

在Object类中,自带了几个常用的方法,这几个方法任意的子类都会继承,如下图所示:

根据上图,我们把Object类中的常用方法归纳为这么几种:

  1. 构造方法;
  2. hashCode()和equals()方法用来判断对象是否相同;
  3. wait()、wait(long)、wait(long,int)、notify()、notifyAll();
  4. toString()和getClass();
  5. clone();
  6. finalize()

接下来就给各位介绍Object类中的几个常用方法,分别说一下这些方法的功能作用。

1. clone()

1.1. 作用

Object中有两个protected修饰的方法,其中一个就是clone()方法,并且该方法还是一个native方法。

clone()方法用于创建复制出当前类对象的一个副本,得到一个复制对象。

所谓的复制对象,首先会分配一个和源对象(调用clone方法的对象)同样大小的内存空间,在这个内存空间中会创

建出一个新对象;

然后再使用源对象中对应的各个成员,填充新对象的成员,填充完成之后,clone方法会创建返回一个新的相同对

象供外部引用。

1.2. clone源码分析

我们再看看clone()方法源码上的注释,如下图所示:

从这段注释中,我们可以了解到:

  1. 以x为蓝本创建出的副本,与x对象并不相同,这保证了克隆出的对象拥有单独的内存空间;
  2. 源对象和克隆的新对象字节码相同,它们具有相同的类类型,但这并不是强制性的;
  3. 源对象和克隆的新对象利用equals()方法比较时是相同的,但这也不是强制性的。

1.3. Java的浅克隆与深克隆

因为每个类的直接或间接父类都是Object,因此它们都含有clone()方法,但因该方法是protected修饰的,所以

我们不能在类外访问该方法。但如果我们要对一个对象进行复制,可以对clone方法进行复写,而Java中提供了两

种不同的克隆方式,浅克隆(ShallowClone)和深克隆(DeepClone)。

浅克隆

在浅克隆中,如果源对象的成员变量是值类型,则复制一份给克隆对象;

如果源对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,

也就是说源对象和克隆对象的成员变量指向相同的内存地址。

简单说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并

没有复制。

我们可以用下图对浅克隆进行展示:

在Java语言中,通过实现Cloneable接口,默认覆盖Object类的clone()方法就可以实现浅克隆。

深克隆

在深克隆中,无论源对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,

即深克隆将源对象的所有引用对象也复制一份给克隆对象。

简单来说,在深克隆中,除了对象本身被复制外,对象中包含的所有成员变量也将复制。我们可以用下图对深克

隆进行展示:

在Java语言中,如果需要实现深克隆,可以通过实现Cloneable接口,自定义覆盖Object类的clone()方法实现,

也可以通过序列化(Serialization)等方式来实现。如果引用类型里面还包含很多引用类型,或者内层引用类型的类

里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。

2. hashCode()

2.1. 简介

hashCode()是Object中的一个native方法,也是所有类都拥有的一个方法,主要是返回每个对象十进制的hash

值。hash值是由hash算法根据对象的地址、对象中的字符串、数字等计算出来的。

一般情况下,相同的对象应会返回相同的哈希吗值,不同的对象会返回不同的哈希码值。

2.2. hash值

哈希值是根据地址值换算出来的一个值,并不是实际的地址值,常用于哈希表中,如HashMap、HashTable、

HashSet。

关于哈希值,不同的JDK算法其实是不一样的:

  • Java 6、7 中会默认返回一个随机数;
  • Java 8 中默认通过和当前线程有关的一个随机数 + 三个确定值,运用Marsaglia’s xorshift scheme的随机数算法得到的一个随机数。

2.3. 案例

以上两个对象的hash值是不同的,表示这是不同的两个对象。

3. equals(obj)

3.1. 简介

Object中的equals方法用于判断this对象和obj本身的值是否相等,即用来判断调用equals方法的对象和形参obj

所引用的对象是否是同一对象。所谓同一对象,就是指两个对象是否指向了内存中的同一块存储单元地址。如果

this和obj指向的是同一块内存单元地址,则返回true;如果this和obj指向的不是同一块内存单元地址,则返回

false。如果没有指向同一内存单元,即便是内容完全相等,也会返回false。

Object类的equals方法,其作用是比较两个对象是否相同,默认比较的是内存地址,其底层是通过==实现的。

如果我们不想比较内存地址,那么就需要重写equals方法。

默认的实现源码如下:

我们知道,Java中还有一个==运算符,也可以对两个对象进行比较。如果是基本数据类型,==比较的是它们的值

是否相同;

如果是引用数据类型,比较的是它们的内存地址是否相同。而equals()方法则是比较两个对象的内容是否相等。

3.2. 使用原则

我们在使用equals()方法时,需注意下面这些原则:

  1. equals()只能处理引用类型变量
  2. 一般情况下,equals()方法比较的是两个引用类型变量的地址值是否相等;
  3. 但是String类、基本类型包装类、File类、Date类等,都重写了Object类的equals()方法,比较是两个对象的"具体内容"是否相同。

3.3. 基本特性

另外Java语言规范也要求equals方法具有下面的特性:

  1. 自反性:对于任何非空引用x,x.equals(x)应该返回true;
  2. 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true;
  3. 传递性:对于任何引用x,y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true;
  4. 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应该返回同样的结果;
  5. 对于任何非空引用x,x.equals(null)应该返回false。

3.4. 案例

从上面的案例中,我们也可以证明,equals()方法用于处理引用类型的变量,默认比较的是两个引用类型的变量地

址是否相等。

4. getClass()

4.1. 简介

getClass()方法可以用于获取对象运行时的字节码类型,得到该对象的运行时的真实类型。

该方法属于Java的反射机制,其返回值是Class类型,例如 Class c =  obj.getClass();。

通过对象c,我们可以进一步获取该对象的所有成员方法,每个成员方法都是一个Method对象。

我们也可以获取该对象的所有成员变量,每个成员变量都是一个Field对象。

同样的,我们也可以获取该对象的构造函数,构造函数则是一个Constructor对象。

4.2. 案例

从上面的代码案例中,我们可以得知,getClass方法用于返回该对象的真实类型(运行时的类型),

可以根据对象的字节码来判断两个对象是否是同一个对象。

5. toString()

5.1. 简介

toString()方法可以说是一个进行“自我描述”的方法,可以返回某个对象的字符串,

当要输出某个实例对象的信息时,我们可以通过重写该方法来输出自我描述的信息。

该方法通常只是为了方便输出本类的描述信息,比如执行System.out.println("xyz")这样的日志语句。

一般情况下,当程序要输出一个对象或者把某个对象和字符串进行连接运算时,

系统就会自动调用该对象的toString()方法返回该对象的字符串表示。

Object类的toString()方法会返回“运行时的类名@十六进制哈希码”格式的字符串,但很多类都重写了 Object

类的toString()方法,用于返回可以表述该对象信息的字符串。

5.2. 案例

上述代码执行结果如下图所示:

从上面程序的运行结果可以发现,默认情况下,对象带不带toString()方法,其最终的输出结果是一样的,

即对象输出时一定会调用 Object类中的 toString()方法打印内容,所以我们可以利用此特性来通过 toString()方

法取得一些对象的信息。

6. wait()、wait(long)、wait(long,int)、notify()、notifyAll()

这几个函数体现的是Java的多线程机制,一般是结合synchronize语句使用

  • wait()用于让当前线程失去操作权限,当前线程进入等待序列;
  • notify()用于随机通知一个持有对象的锁的线程获取操作权限;
  • wait(long) 和wait(long,int)用于设定下一次获取锁的距离当前释放锁的时间间隔;
  • notifyAll()用于通知所有持有对象的锁的线程获取操作权限

这几个方法我们后面在分析多线程的面试题时再细说,此处先仅做了解。

7. finalize()

7.1. 简介

finalize()方法在进行垃圾回收的时候会用到,主要是在垃圾回收时,用于作为确认该对象是否确认被回收的一个

标记。

我们在使用finalize()方法时要注意:

● finalize方法不一定会执行,只有在该方法被重写的时候才会执行;

● finalize方法只会被执行一次;

● 对象可以在finalize方法中获得自救,避免自己被垃圾回收,同样的自救也只能进行一次;

● 不推荐Java程序员手动调用该方法,因为finalize方法代价很大。

7.2. 案例

为了测试出finalize()方法的作用,给大家设计了如下案例:

然后我们对Dog对象进行回收测试:

要想确保finalize()方法的执行,我们首先需要在相关对象中重新finalize()方法,然后将待回收的对象手动标记为

null,最后再手动调用gc()方法,这样才有可能确保finalize()方法一定执行。

四、总结

至此就把Object类给大家介绍完毕了,这个类的内容并不是很难,主要是掌握几个常用的方法就可以了,尤其是

equals()、hashCode()、toString()、getClass()等方法。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
并查集维护到祖宗距离是指在并查集的数据结构中,除了记录每个元素的父节点外,还记录了每个元素到其祖宗节点的距离。这样可以在查找祖宗节点的同时,更新每个元素到祖宗节点的距离。这个功能可以通过路径压缩来实现。路径压缩是指在查找祖宗节点的过程中,将路径上的每个节点的父节点直接指向祖宗节点,从而减少后续查找的时间复杂度。在路径压缩的过程中,还可以同时更新每个节点到祖宗节点的距离。这样,在后续的操作中,可以直接通过查找元素的祖宗节点来获取元素到祖宗节点的距离,而无需再次进行计算。引用\[1\]中的代码是一个实现路径压缩的示例,其中的d数组就是用来记录每个元素到祖宗节点的距离。引用\[2\]和引用\[3\]中也提到了路径压缩的概念和实现方式。 #### 引用[.reference_title] - *1* [AcWing 238. 银河英雄传说--(维护size和到祖宗节点距离)带权并查集](https://blog.csdn.net/qq_45748404/article/details/117967117)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [算法基础课—数据结构(六) 并查集](https://blog.csdn.net/Yttttttttttttttt/article/details/117067020)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值