JDK源码解析之 Java.lang.Object

Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起。作为其他所有类的基类,Object具有哪些属性和行为,是Java语言设计背后的思维体现。

Object类位于java.lang包中,java.lang包包含着Java最基础和核心的类,在编译时会自动导入。Object类没有定义属性,一共有13个方法:

1、类构造器public Object();

大部分情况下,Java中通过形如 new A(args…)形式创建一个属于该类型的对象。其中A即是类名,A(args…)即此类定义中相对应的构造函数。通过此种形式创建的对象都是通过类中的构造函数完成。为体现此特性,Java中规定:在类定义过程中,对于未定义构造函数的类,默认会有一个无参数的构造函数,作为所有类的基类,Object类自然要反映出此特性,在源码中,未给出Object类构造函数定义,但实际上,此构造函数是存在的。

当然,并不是所有的类都是通过此种方式去构建,也自然的,并不是所有的类构造函数都是public。

2、private static native void registerNatives();

registerNatives函数前面有native关键字修饰,Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。方法的具体实现体在dll文件中,对于不同平台,其具体实现应该有所不同。用native修饰,即表示操作系统,需要提供此方法,Java本身需要使用。具体到registerNatives()方法本身,其主要作用是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦。

既然如此,可能有人会问,registerNatives()修饰符为private,且并没有执行,作用何以达到?其实,在Java源码中,此方法的声明后有紧接着一段静态代码块:

1 private static native void registerNatives();
2 static {
3     registerNatives();
4 }
3、protected native Object clone() throws CloneNotSupportedException;

clone()方法又是一个被声明为native的方法,因此,我们知道了clone()方法并不是Java的原生方法,具体的实现是有C/C++完成的。clone英文翻译为"克隆",其目的是创建并返回此对象的一个副本,而克隆出来的副本与原来的对象没有任何关系的。Java术语表述为:clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。

4、public final native Class<?> getClass();

getClass()也是一个native方法,返回的是此Object对象的类对象/运行时类对象Class<?>。效果与Object.class相同。

首先解释下"类对象"的概念:在Java中,类是是对具有一组相同特征或行为的实例的抽象并进行描述,对象则是此类所描述的特征或行为的具体实例。作为概念层次的类,其本身也具有某些共同的特性,如都具有类名称、由类加载器去加载,都具有包,具有父类,属性和方法等。于是,Java中有专门定义了一个类,Class,去描述其他类所具有的这些特性,因此,从此角度去看,类本身也都是属于Class类的对象。为与经常意义上的对象相区分,在此称之为"类对象"。

5、public boolean equals(Object obj);

Object类中关于equals()方法的定义:

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

由此可见,Object原生的equals()方法内部调用的正是==,与==具有相同的含义。既然如此,为什么还要定义此equals()方法?

equlas()方法的正确理解应该是:判断两个对象是否相等。那么判断对象相等的标尺又是什么?

如上,在object类中,此标尺即为==。当然,这个标尺不是固定的,其他类中可以按照实际的需要对此标尺含义进行重定义。如String类中则是依据字符串内容是否相等来重定义了此标尺含义。如此可以增加类的功能型和实际编码的灵活性。当然了,如果自定义的类没有重写equals()方法来重新定义此标尺,那么默认的将是其父类的equals(),直到object基类。

6、public native int hashCode();

hashCode()方法返回一个整形数值,表示该对象的哈希码值。

hashCode()具有如下约定:

1).在Java应用程序程序执行期间,对于同一对象多次调用hashCode()方法时,其返回的哈希码是相同的,前提是将对象进行equals比较时所用的标尺信息未做修改。在Java应用程序的一次执行到另外一次执行,同一对象的hashCode()返回的哈希码无须保持一致;

2).如果两个对象相等(依据:调用equals()方法),那么这两个对象调用hashCode()返回的哈希码也必须相等;

3).反之,两个对象调用hasCode()返回的哈希码相等,这两个对象不一定相等。

即严格的数学逻辑表示为: 两个对象相等 <=> equals()相等 => hashCode()相等。因此,重写equlas()方法必须重写hashCode()方法,以保证此逻辑严格成立,同时可以推理出:hasCode()不相等 => equals()不相等 <=> 两个对象不相等。

可能有人在此产生疑问:既然比较两个对象是否相等的唯一条件(也是冲要条件)是equals,那么为什么还要弄出一个hashCode(),并且进行如此约定,弄得这么麻烦?

其实,这主要体现在hashCode()方法的作用上,其主要用于增强哈希表的性能。

以集合类中,以Set为例,当新加一个对象时,需要判断现有集合中是否已经存在与此对象相等的对象,如果没有hashCode()方法,需要将Set进行一次遍历,并逐一用equals()方法判断两个对象是否相等,此种算法时间复杂度为o(n)。通过借助于hasCode方法,先计算出即将新加入对象的哈希码,然后根据哈希算法计算出此对象的位置,直接判断此位置上是否已有对象即可。(注:Set的底层用的是Map的原理实现)

在此需要纠正一个理解上的误区:对象的hashCode()返回的不是对象所在的物理内存地址。甚至也不一定是对象的逻辑地址,hashCode()相同的两个对象,不一定相等,换言之,不相等的两个对象,hashCode()返回的哈希码可能相同。

7、public String toString();

toString()方法返回该对象的字符串表示。先看一下Object中的具体方法体:

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

toString()方法我们会经常用到,即使没有显式调用,但当我们使用System.out.println(obj)时,其内部也是通过toString()来实现的

toString()是由对象的类型和其哈希码唯一确定,同一类型但不相等的两个对象分别调用toString()方法返回的结果可能相同。

8/9/10/11/12、wait(…) / notify() / notifyAll()

wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。这几个方法主要用于java多线程之间的协作.

wait():调用此方法所在的当前线程等待,直到在其他线程上调用此方法的主调(某一对象)的notify()/notifyAll()方法。

notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。

wait(long timeout)/wait(long timeout, int nanos):调用此方法所在的当前线程等待,直到在其他线程上调用此方法的主调(某一对象)的notisfy()/notisfyAll()方法,或超过指定的超时时间量。

notify()/notifyAll():唤醒在此对象监视器上等待的单个线程/所有线程。

wait(…) / notify() | notifyAll()一般情况下都是配套使用。

13、protected void finalize();

finalize方法主要与Java垃圾回收机制有关。首先我们看一下finalized方法在Object中的具体定义:

1 protected void finalize() throws Throwable { }

我们发现Object类中finalize方法被定义成一个空方法,为什么要如此定义呢?finalize方法的调用时机是怎么样的呢?

首先,Object中定义finalize方法表明Java中每一个对象都将具有finalize这种行为,其具体调用时机在:JVM准备对此对形象所占用的内存空间进行垃圾回收前,将被调用。由此可以看出,此方法并不是由我们主动去调用的(虽然可以主动去调用,此时与其他自定义方法无异)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/535794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将z-blog改成英文blog所遇到的问题

1.将z-blog中文章日期中的“年,月,日”改成英文 相关模板:b_article-multi.htmlb_article-single.html默认用的时间标签是<#article/posttime/longdate#> 即 "2007年1月13日" 这样的形式你可以换成 <#article/posttime/shortdate#>即 "2…

JDK源码解析之 Java.lang.String

String 类代表字符串。Java 程序中的所有字符串字面值&#xff08;如 “abc” &#xff09;都作为此类的实例实现。 字符串是常量&#xff1b;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的&#xff0c;所以可以共享。 一、类定义 p…

看到一个blog的标语,有意思!

"上世纪80年代勇气&#xff0c;90年代靠关系&#xff0c;现在必须靠知识能力&#xff01;挣钱靠1、兴趣广泛&#xff1b; 2、感觉敏锐&#xff1b; 3、集中力强&#xff1b; 4、个性不脆弱&#xff08;坚韧性&#xff09;&#xff1b; 5、能在瞬间了解因果关系&#xff1b…

JDK源码解析之 Java.lang.AbstractStringBuilder

这个抽象类是StringBuilder和StringBuffer的直接父类&#xff0c;而且定义了很多方法&#xff0c;因此在学习这两个类之间建议先学习 AbstractStringBuilder抽象类 该类在源码中注释是以JDK1.5开始作为前两个类的父类存在的&#xff0c;可是直到JDK1.8的API中&#xff0c;关于S…

RHEL下安装配置基于2台服务器的MYSQL集群

一、介绍这篇文档旨在介绍如何在RHEL下安装配置基于2台服务器的MySQL集群。并且实现任意一台服务器出现问题或宕机时MySQL依然能够继续运行。 注意&#xff01;虽然这是基于2台服务器的MySQL集群&#xff0c;但也必须有额外的第三台服务器作为管理节点&#xff0c;但这台服务器…

JDK源码解析之 Java.lang.StringBuffer

StringBuffer类表示一个可变的字符序列。StringBuffer的API与StringBuilder互相兼容&#xff0c;但是StringBuffer是线程安全的。在可能的情况下&#xff0c;建议优先使用StringBuilder&#xff0c;因为在大多数实现中它比StringBuffer更快。 一、类定义 public final class S…

redo和undo

这是在网上看到的对redo和undo的探讨&#xff1a; 1. redo 记录所有做过的事情&#xff0c;用于恢复 undo 记录事务的前镜相&#xff0c;用于回滚2. redo&#xff0c;恢复数据库时&#xff0c;按照重做日志文件来恢复你之前的操作 undo&#xff0c;撤消你做过的操作&#xff0…

JDK源码解析之 Java.lang.StringBuilder

StringBuilder类表示一个可变的字符序列。StringBuilder的API与StringBuffer互相兼容&#xff0c;但是StringBuilder是非线程安全的&#xff0c;在大多数实现中它比StringBuffer更快。 一、类定义 public final class StringBufferextends AbstractStringBuilderimplements ja…

从映射观点看索引

信息检索主要有“检”与“索&#xff08;办手续&#xff09;”两个动作。在图书馆借书时&#xff0c;一般而言&#xff0c; 找书的时间比办理手续的时间长得多&#xff0c;因而缩短检查时间是提高效率的关键。数据库中检 索信息也与此类似。 在没有索引文件时&#xff0c;DBM…

JDK源码解析之 Java.lang.Boolean

Boolean 类是将 boolean 基本类型进行包装。类型为 Boolean 的对象包含一个单一属性 value&#xff0c;其类型为 boolean。 此外还提供了许多将 boolean 转换为 String、String 转换为 boolean&#xff0c;以及其他一些方法。 一、类定义 public final class Boolean implemen…

MYSQL的集群的安装与配置(mysql-5.1.21)

具体安装与配置&#xff1a;1&#xff09;准备工作&#xff1a;6台机器&#xff0c;IP地址分别为192.168.0.&#xff08;231-236&#xff09;MGM节点&#xff1a;192.168.0.231(232)SQL 节点&#xff1a;192.168.0.233-234NDBD 节点&#xff1a;192.168.0.235-236系统都是REDHA…

JDK源码解析之 Java.lang.Byte

byte&#xff0c;即字节&#xff0c;由8位的二进制组成。在Java中&#xff0c;byte类型的数据是8位带符号的二进制数,以二进制补码表示的整数 取值范围&#xff1a;默认值为0&#xff0c;最小值为-128&#xff08;-27&#xff09;;最大值是127&#xff08;27-1&#xff09; Byt…

在命令行模式下管理SELinux

作者&#xff1a; Oslad.com (原创&#xff01;转载请注明出处) 2006-07-14 在 GUI 图形界面模式下&#xff0c;要更改 SELinux 的策略使用方式&#xff0c;只需依次点击“应用程序”&#xff0c;“系统设置”&#xff0c;“安全级别”&#xff1b;然后在“安全级别配置”对…

JDK源码解析之 Java.lang.Double

Double类是原始类型double的包装类&#xff0c;它包含若干有效处理double值的方法&#xff0c;如将其转换为字符串表示形式&#xff0c;反之亦然。Double类的对象可以包含一个double值。 Double类包装原始类型的值 double中的对象。类型的对象 Double包含一个类型为的字段 doub…

网页搜索帮助-禁止搜索引擎收录的方法

什么是robots.txt文件?搜索引擎使用spider程序自动访问互联网上的网页并获取网页信息。spider在访问一个网站时&#xff0c;会首先会检查该网站的根域下是否有一个叫做robots.txt的纯文本文件。您可以在您的网站中创建一个纯文本文件robots.txt&#xff0c;在文件中声明该网站…

JDK源码解析之 Java.lang.Float

Float类是原始类型float的包装类&#xff0c;它包含若干有效处理浮点值的方法&#xff0c;如将其转换为字符串表示形式&#xff0c;反之亦然。Float类的一个对象可以包含一个浮点值 一、类定义 public final class Float extends Number implements Comparable<Float> {…

FTP两种工作模式:主动模式(Active FTP)和被动模式(Passive FTP)

在主动模式下&#xff0c;FTP客户端随机开启一个大于1024的端口N向服务器的21号端口发起连接&#xff0c;然后开放N1号端口进行监听&#xff0c;并向服务器发出PORT N 1命令。服务器接收到命令后&#xff0c;会用其本地的FTP数据端口&#xff08;通常是20&#xff09;来连接客户…

JDK源码解析之 java.lang.Integer

teger 基本数据类型int 的包装类 Integer 类型的对象包含一个 int 类型的字段 一、类定义 public final class Integer extends Number implements Comparable<Integer>{}类被声明为final的,表示不能被继承;继承了Number抽象类,可以用于数字类型的一系列转换;实现了Comp…

Loadrunner的基本概念

1)vuser_init(only one &#xff0c;重复执行脚本的时候&#xff0c;此部分只会执行一次 ) %G< rJc*P 2)action( 一个或者多个 , 重复执行脚本的时候&#xff0c;只有该部分会按重复的次数重复执行 ) z*Xfjy(Mj 3)vuser_end(only one, 重复执行脚本的时候&#xff0c;此…

JDK源码解析之 java.lang.Long

Long 与Integer 是数值类型中使用频率最高的两个,也是提供支持方法最多的两个 他们提供出来的方法功能也是高度的相似 一、类定义 public final class Long extends Number implements Comparable<Long> {}类被声明为final的,表示不能被继承;继承了Number抽象类,可以用于…