一、Object类概述

  Object类是java中类层次的根,是所有类的基类。在编译时会自动导入。Object中的方法如下:
![](https://img2018.cnblogs.com/blog/1195929/201904/1195929-20190413184508312-1759109771.png)

二、方法详解

  Object的方法可以分成两类,一类是被关键字`final`修饰的的方法,这类方法能被子类覆盖。另一类是没有`final`修饰,它们可以被子类重写。

构造方法:Object()

  在Object中没有显式的构造方法,这个只是创建一个Object对象,没有什么可以说的。

getClass()

  getClass被`final`修饰,不能被子类重写。它返回的是正在运行的对象的Class对象。并且本方法被`native`修饰,其具体实现是在本地C(C++)方法。应为java无法与一些底层系统直接交互,这个时候就可以通过native方法通过非java语言间接交互。想更多的了解`native`可以参考这篇文章[(了解native)](https://xzknet.iteye.com/blog/274122),你也可以自己在java中通过native调用c写的方法[(看这里)](https://blog.csdn.net/zmx729618/article/details/50779924)。

equals(Object obj)

  表明`obj`是否“equals to”本对象。在Object中的equals返回的是两个对象是否相同(指两个对象是同一个对象)

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

如果我们要实现本对象上逻辑相等的概念时,可以考虑在子类中重写该方法。但必须遵守一些准则:

  • 自反性(reflexive)。对任务非null的对象x,x.equals(x)必须返回true
  • 对称性(symmetric)。对任何非null的x,y,x.equals(y)返回true,y.equals(x)也必须返回true
  • 传递性(transitive)。对任何非null的x,y,z。x.equals(y)返回truey.equals(z)返回true,则x.equals(z)必须返回true
  • 一致性(consistent)。对任何非null的引用x,y,只要对象内的信息没有被修改,则多次调用的结果一致。
  • 非null的引用x,x.equals(null)返回false

hashCode()

  该对象放回对象的hash值,这个是为了可以应用在一些使用对象hash的容器中,如`HashMap`等。这也是一个本地方法调用。在每一个覆盖了equals方法的类中都必须覆盖hashCode(这是Object.hashCode的通用约定)。
* 只要equals中所用到的对象的信息没有被修改,那么多次调用hashCode的返回值相同。
* 如果两个对象的equals比较是相同的,那么两个对象调用hashCode返回相同的整数值。
* 如果两个对象的equals比较是不同的,两个对象的hashCode返回值不一定不同。但是如果我们提供equals不同的对象中提供不同的hashCode返回值,可能提高散列表的性能。
你也可以查看一下hashMap或者HashSet的源码中用于对象的比较,就更能体会到为什么要在重写equals的情况下重写hashCode了。

clone()

  创建并返回本对象的一个副本,是一个native方法。`x.clone()!=x`,`x.clone().getClass()==x.getClass()`,`x.clone().equals(x)==true`。但是如果需要覆盖本方法,上述的要求并不是必须遵守的。如果一个类实现了Cloneable,Object的clone方法就返回该对象的逐域拷贝(返回的对象和原来的对象不易同一个对象),如果没有实现Cloneable接口,将会抛出`CloneNotSupportedException`异常。测试代码下面,你可以将Cloneable接口去掉试试:

public class Main {

public static void main(String args[]) {
Student stu = new Student("fanl",18);
Student classMate = new Student("xiaoming",18);
stu.setClassMate(classMate);
Student stuCopy = null;
try {
stuCopy = (Student) stu.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(stu);
System.out.println(stuCopy);
System.out.println(stu.classMate);
System.out.println(stuCopy.classMate);
}
} class Student implements Cloneable{
public String name;
public int age;
public Student classMate; public void setClassMate(Student classMate) {
this.classMate = classMate;
}
public Student(String name,int age) {
this.name = name;
this.age = age;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
} }

还有一点需要注意的是Object.clone()实现的是浅拷贝,如果对象的域中含有对象A的引用,那么copy的只是引用(即clone得到的对象和原对象指向同一个对象A)

toString()

   Object中该方法的实现如下:

public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

可以看出该方法的返回值就是类名加上hashCode的十六进制表示,所以在子类中最好重写本方法,使其更便于阅读。

notify(),wait()

  `notify()`唤醒一个在本对象监视器上等待的的线程,`wait()`使本进程在某个对象锁上等待。`Obj.notify()`,`obj.wait()`必须要与`synchronized(Obj)`一起使用,也就是notify和wait是针对已经获取了Obj锁进行的操作,`notify()`与`wait()`是相对的,`wait()`是线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。`wait()`和`notify()`都执行在synchronize语句块中。
下面是一个例子,会按顺序的打印出"ACB"

public class Main implements Runnable {

private String name;
private Object prev;
private Object next; private Main(String name, Object prev, Object next) {
this.name = name;
this.prev = prev;
this.next = next;
} @Override
public void run() {
int count = 10;
while (count > 0) {
synchronized (prev) {
synchronized (next) {
System.out.print(name);
count--; next.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
Main pa = new Main("A", c, a);
Main pb = new Main("B", a, b);
Main pc = new Main("C", b, c); new Thread(pa).start();
new Thread(pb).start();
new Thread(pc).start();
}
}

next.notify();会唤醒在next上waiting的进程,之后将自己waiting在pre的对象锁上。这样在一个对象锁上唤醒一个进程,在另一个对象锁上wait本进程,循环往复。另外还有两个重载的wait方法,目的是为等待加上超时设置。

注意:Thread.sleep()与Object.wait()二者都可以暂停当前线程,释放CPU控制权,主要的区别在于Object.wait()在释放CPU同时,释放了对象锁的控制。

notifyAll()

  唤醒在这个对象上等待的所有进程。

finalize()

当垃圾收集确定不再引用对象时,由对象上的垃圾收集器调用。子类覆盖finalize方法来处理系统资源或执行其他清理。在《Effective Java》中作者建议我们避免使用该方法。详细说明可以参考《Effective Java》(经典之作)。

总结

  在写本博文时,参考了《Effective Java》,其中有些东西本文只是略微提及。读者可以翻阅这本书了解更多具体情况。其中Object中的方法的准确使用在《Effective Java》(第二版)的第三章有详细的说明。

java源码解析之Object类的更多相关文章

  1. java源码解析之String类(二)

    上一节主要介绍了String类的一些构造方法,主要分为四类 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并 ...

  2. java源码解析之String类(一)

    String是我们接触最多的类,无论是学习中还是工作中,基本每天都会和字符串打交道,从字符串本身的各种拼接.切片.变形,再到和其他基本数据类型的转换,几乎无时无刻都在使用它,今天就让我们揭开Strin ...

  3. java源码解析之String类(三)

    上一节我们主要讲了String类的一些不是很常用的方法,其中需要掌握的如下,我就不再赘述了 public int length() public boolean isEmpty() public by ...

  4. java源码解析之String类(五)

    /* * 切片函数,非常重要,这里一定要牢记beginIndex是开始位置,endIndex是结束位置,区别于以前学的offset是开始位置,而count或length是个数和长度 * 比如说,new ...

  5. java源码解析之String类(四)

    /* * 返回指定字符第一次出现的字符串内的索引 */ public int indexOf(int ch) { return indexOf(ch, 0); } /* * 返回指定字符第一次出现的字 ...

  6. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  7. 【Java源码解析】Thread

    简介 线程本质上也是进程.线程机制提供了在同一程序内共享内存地址空间运行的一组线程.对于内核来讲,它就是进程,只是该进程和其他一下进程共享某些资源,比如地址空间.在Java语言里,Thread类封装了 ...

  8. Java源码解析——集合框架(三)——Vector

    Vector源码解析 首先说一下Vector和ArrayList的区别: (1) Vector的所有方法都是有synchronized关键字的,即每一个方法都是同步的,所以在使用起来效率会非常低,但是 ...

  9. Java源码解析——集合框架(二)——ArrayBlockingQueue

    ArrayBlockingQueue源码解析 ArrayBlockingQueue是一个阻塞式的队列,继承自AbstractBlockingQueue,间接的实现了Queue接口和Collection ...

随机推荐

  1. ToList和ToDataTable(其中也有反射的知识)

    using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Refle ...

  2. MyEclipse中Web项目文件名上红色和黄色感叹号处理

      MyEclipse中Web项目文件名上红色和黄色感叹号处理     先说红色感叹号: 那就是代表错误,说明你引用的JAR包位置无效,所以,你应该重新将包导入到工程里面去,这个具体应该会吧,如果是初 ...

  3. 年末福利,C/S应用升级更新完整解决方案放送

    程序员,工作累寿命短,大家应该学会分享,别浪费有限的生命与健康做重复的事情. C/S方式实现的应用有个升级更新功能是必需的,以前整过一个但是没考虑多套C/S应用的情况,那个时候公司只有一套系统,现在又 ...

  4. Gym 101201I Postman (贪心)

    题意:有个邮递员,要送信,每次最多带 m 封信,有 n 个地方要去送,每个地方有x 封要送,每次都到信全送完了,再回去,对于每个地方,可以送多次直到送够 x 封为止. 析:一个很简单的贪心,就是先送最 ...

  5. Photoshop 原画绘制

    ... <伯里曼> 手绘.鼠绘和板绘.

  6. SQL SERVER 2012数据库:开启防火墙导致外部无法连接数据库解决办法

    SQL SERVER 2012数据库:开启防火墙导致外部无法连接数据库解决办法 将以下代码存为OpenSqlServerPort.bat文件: netsh advfirewall firewall a ...

  7. 团体程序设计天梯赛L2-024 部落 2017-04-18 11:31 274人阅读 评论(0) 收藏

    L2-024. 部落 时间限制 120 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不 ...

  8. ETL 运行维护

    装载数据仓库过程中,不管作业是实时执行还是批处理方式执行,其调度时间,执行顺序和执行环境都是关键点. 本章描述创建一个ETL操作策略,来保证数据仓库的数据即时可用. ETL执行策略分为两种:1 调度 ...

  9. handsontable-developer guide-cell type

    单元格类型:这里有很多没见过的用法,得好好总结一下 //预定义的类型Text Numeric Checkbox Date Select Dropdown Autocomplete Password H ...

  10. [Delphi]编译条件

    当软件在多个DELPHI版本下编译时,需要处理各版本的不同情况,使用编译条件技术实现. 万一博客,编译指令基础使用介绍:http://www.cnblogs.com/del/category/1686 ...