接口和抽象类是否继承了Object

  我们先看一下Java的帮助文档对于Object的描述:

Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.

Object 类是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

  注意:描述是Every class(所有的类)。有这句话可以猜想一下,抽象类是继承了Object。

  对于继承,我们知道C++语言支持多继承,Java语言只支持单继承。那么Java语言为什么不支持多继承呢?我们先看一看多继承中最典型的钻石问题(菱型缺陷),如下图(图片来源于https://www.cnblogs.com/sddai/p/6516668.html):

  其中A、B、C、D是四个类,B继承A,C也继承A,D又同时继承了B和C。如果B和C都有test方法,看如下代码

D d = new D();
d.test();

  第一句中当new D(); 的时候会不会调用两次A的构造函数?

  第二句中调用的是B里面的test方法还是C里面的test方法?

  为了避免以上的问题,Java采用了折衷的方法,只允许单继承,但可以实现多个接口。所以我们可以以java语言是单继承这个前提,来推导一下接口和抽象类是否继承Object。如下:

  对于抽象类而言:一个普通类肯定是继承了Object,如果一个抽象类再继承这个普通类,这个时候抽象类肯定也是继承了Object的。而对于没有继承任何类的抽象类而言,如果它没有继承Object,那么当一个普通类继承这个抽象类的时候,这个普通类也肯定没有继承Object,悖论。所以抽象类肯定是继承了Object。

  对于接口而言呢:如果接口继承了Object类。那么当一个类实现多个接口的时候,那不就相当于继承了多遍Object?又变成了多继承?这个问题先放一放。

  到目前为止,以上的言论还都处于猜想阶段,现在我们就来深入一点,找一下确凿的“证据”。我们都知道Java源文件会先编译成class文件,然后再被jvm执行。那么如果我们能够知道父类在class文件中是怎么存储的,然后看一下接口编译成的class文件,不就知道接口是否继承Object了吗?以下内容涉及字节码,来源于《深入理解Java虚拟机》第二版的6.3节(核心是6.3.4节)。

  Java文件编译而成的class文件是二进制文件,没有任何分隔符,所以无论是顺序还是数量都是被严格规定的。

  class文件开始的4个字节是 CAFEBABE,表示这是一个能被虚拟机接受的class文件;紧跟着4个字节表示class文件的版本号;紧接着后面是常量池,前两个字节是常量中的常量数量,后面是常量池的内容;常量池后面的2个字节代表访问标志,比如是否public、接口、注解、枚举等;紧接着2个字节代表类的索引;类索引后面两个字节代表父类索引;父类索引后面是接口索引集合,前两个字节代表集合的大小,后面跟具体的接口索引。如下图所示:

 

注:

  1. 由于常量池中常量的数量是用两个字节存储的,也就是说单个class文件中的常量池中常量的个数不会超过2个字节。

  2. “索引” 是指在常量池中的第几项常量(从1开始),占两个字节(和常量池中的常量数量占用空间一样)。比如类索引为5,表示类的全类名在常量池中的第5个常量处。

  3. 父类索引只使用了两个字节,这也说明了在class文件中父类最多存在一个(除了Object类的父类索引为0外,其他都有值)。

  可见,我们只需找出常量池的结尾,即可找出父类索引,从而确定一个类的父类是谁?jdk中有一个javap的命令(javap -v xxx)。可以查看一个类的常量池,从而查看常量池中最后一个常量的值,然后再根据class文件找出对应的值,即可确定常量池的末尾。

例:TestJ1.java 如下:

public class TestJ1 {
}

  使用UltraEdit打开TestJ1.class文件,使用命令行输入命令:“javap -v TestJ1”。如下图所示: 

  由图中可知常量池最后一个常量为”java/lang/Object” (Constant pool 为常量池),在class文件中对应的位置为0x0069~0X0078。所以访问标志的位置为0x0079~0x007a,值为:0x0021;同理类索引的值为:0x0002;父类索引值为:0x0003;接口索引集合长度为:0x0000(该类没有实现接口)。

  类索引为:0x0002,换算成10进制是2,找常量池中为#02(#02 表示常量池中的第二项常量)的值,为 #11,再找#11,为Test1(此处为类的全类名。由于TestJ1类没有包,所以是类名。格式如java/lang/Object)。同理父类为:0x0003 --> #3 --> #12 --> java/lang/Object。所以TestJ1继承Object类。

 

接下来我们写一个最简单的接口如下:

public interface InterSuper1 {}

 class文件和常量池如下:

  由上图可以看出在class文件中InterSuper1接口的父类标识符指向的也是Object类。不止如此,如果一个接口有父接口。那么此接口的父类标识符指向的也是Object类。可以说对于class文件而言所有接口的父类都是Object(同理也可证明Object类也是所有抽象类的父类)

  现在我们再回过头看一看上面遗留的问题:如果接口继承了Object类。那么当一个类实现多个接口的时候,那不就相当于继承了多遍Object?又变成了多继承?首先不会继承多遍Object,因为在class文件而言,只能存储一个父类。这个类还是直接或者间接的继承Object。也是单继承,由于接口不能实例化,所以也不会出现上面的菱形缺陷。

  至于网上流传的Java 的标准——“Java Language Specification”中的9.2节,如下(来源于http://www.cnblogs.com/softnovo/articles/4546418.html):

  我的理解是:首先这段话没有明确说明接口不继承Object;其次它是出自于java语言规范中,所以它的目的是让人们更加容易使用Java,所以故意省略了这个细节也是有可能的;再者如果接口继承Object,上面的观点也能说得通。

  还有一个是如下代码,为什么不输出Object中的方法?这个我也无法解释。

 

public interface SuperInter {public void test();public String getString();
}public static void main(String[] args) {Method[] methods = SuperInter.class.getMethods();for (Method method : methods) {System.out.println(method.getName());}
}

 

参考资料:

  《深入理解Java虚拟机》第二版

  https://www.cnblogs.com/sddai/p/6516668.html

  http://www.cnblogs.com/softnovo/articles/4546418.html

  https://blog.csdn.net/xidiancoder/article/details/78011148

  https://blog.csdn.net/tengfeixiaoao/article/details/79586949

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

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

相关文章

3.2)深度学习笔记:机器学习策略(2)

目录 1)Carrying out error analysis 2)Cleaning up Incorrectly labeled data 3)Build your first system quickly then iterate 4)Training and testing on different distributios 5)Bias and Variance with m…

【CodeForces - 674B 】Bear and Two Paths(贪心,思维,水题)

题干: 第一行给出N和M代表有N个难度1~N的题目,M代表有M个约束。接下来M行,每行两个数代表这一个约束的两个题目。 代表难度的数字越大,题目越难。现在要求你将N个题目分成不重不漏的两组(div1和div2),要求1每组不能为…

4.1)深度卷积网络:卷积神经网络基础

目录 1)Computer vision 2)Edge detection example(理解) 3)More edge detection 4)Padding(重点) 5)Strided convolutions(重点) 6&#x…

【2019icpc南京站网络赛 - H】Holy Grail(最短路,spfa判负环)

题干: As the current heir of a wizarding family with a long history,unfortunately, you find yourself forced to participate in the cruel Holy Grail War which has a reincarnation of sixty years.However,fortunately,you summoned a Caster Servant wi…

4.2)深度卷积网络:实例研究

目录 1)Why look at case studies? 2)Classic networks(理解) 3)ResNets(理解) 4)Why ResNets work?(经典) 5)Networks in Networks and 1…

10种常见的软件架构模式

有没有想过要设计多大的企业规模系统?在主要的软件开发开始之前,我们必须选择一个合适的体系结构,它将为我们提供所需的功能和质量属性。因此,在将它们应用到我们的设计之前,我们应该了解不同的体系结构。 什么是架构模…

4.3)深度卷积网络:目标检测

目录 1)Object localization(重点) 2)Landmark detection 3)Object detection 4)Convolutional implementation of sliding windows 5)Bounding box prediction(重点&#xff0…

【牛客 - 82B】区间的连续段(贪心,建图,倍增)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/82/B 来源&#xff1a;牛客网 给你一个长为n的序列a和一个常数k 有m次询问&#xff0c;每次查询一个区间[l,r]内所有数最少分成多少个连续段&#xff0c;使得每段的和都 < k 如果这一次查询无解…

苹果手机PD快充电压电流全程详解

iphone PD充电策略&#xff0c;一共分为5个阶段。 第①阶段&#xff1a;iphone X电量为0%处于关机状态&#xff0c;这时插入PD充电器iphone会检测是否支持apple 5V2.4A协议&#xff0c;是的话会以5V2.4A进行充电。苹果原厂29w / 61w / 87w PD充电器都是自带 apple 5V2.4A 协议…

4.4)深度卷积网络:人脸识别和神经风格转换

目录 1&#xff09;What is face recognition? 2&#xff09;One-shot learning 3&#xff09;Siamese network 4&#xff09;Triplet Loss&#xff08;重点&#xff09; 5&#xff09;Face Verification and Binary Classification 6&#xff09;What is neural style …

【2019牛客暑期多校训练营(第八场)- G】Gemstones(栈,模拟)

题干&#xff1a; 链接&#xff1a;https://ac.nowcoder.com/acm/contest/888/G 来源&#xff1a;牛客网 Gromah and LZR have entered the seventh level. There are a sequence of gemstones on the wall. After some tries, Gromah discovers that one can take exactly…

一步步编写操作系统 35 内存为何要分页

一直以来我们都直接在内存分段机制下工作&#xff0c;目前未出问题看似良好&#xff0c;的确目前咱们的应用过于简单了&#xff0c;就一个loader在跑&#xff0c;能出什么问题呢。可是想像一下&#xff0c;当我们物理内存不足时会怎么办呢&#xff1f;比如系统里的应用程序过多…

《python深度学习》代码中文注释

《python深度学习》由Keras之父、现任Google人工智能研究员的弗朗索瓦•肖莱&#xff08;François Chollet&#xff09;执笔&#xff0c;详尽介绍了用Python和Keras进行深度学习的探索实践&#xff0c;包括计算机视觉、自然语言处理、生成式模型等应用。书中包含30多个代码示…

【BZOJ - 4754】独特的树叶(树哈希)

题干&#xff1a; JYY有两棵树A和B&#xff1a;树A有N个点&#xff0c;编号为1到N&#xff1b;树B有N1个点&#xff0c;编号为1到N1。JYY知道树B恰好是由树A加上一个叶 节点&#xff0c;然后将节点的编号打乱后得到的。他想知道&#xff0c;这个多余的叶子到底是树B中的哪一个…

一步步编写操作系统 36 一级页表与虚拟地址1

为了给大家说清楚分页机制&#xff0c;我们先在宏观上说下cpu地址变换过程&#xff0c;先让大家有个直观的印象&#xff0c;如果有不明白的地方也不要着急&#xff0c;适时地不求甚解&#xff0c;有助于从全局上将知识融会贯通&#xff08;这句话是我即兴说的&#xff0c;说得多…

动手学无人驾驶(4):基于激光雷达点云数据3D目标检测

上一篇文章《动手学无人驾驶&#xff08;3&#xff09;&#xff1a;基于激光雷达3D多目标追踪》介绍了3D多目标追踪&#xff0c;多目标追踪里使用的传感器数据为激光雷达Lidar检测到的数据&#xff0c;本文就介绍如何基于激光雷达点云数据进行3D目标检测。 论文地址&#xff1a…

【BZOJ - 4337】BJOI2015 树的同构(树哈希)

题干&#xff1a; 树是一种很常见的数据结构。 我们把N个点&#xff0c;N-1条边的连通无向图称为树。 若将某个点作为根&#xff0c;从根开始遍历&#xff0c;则其它的点都有一个前驱&#xff0c;这个树就成为有根树。 对于两个树T1和T2&#xff0c;如果能够把树T1的所有点…

一步步编写操作系统 37 一级页表与虚拟地址2

接上节&#xff0c;分页机制是建立在分段机制之上&#xff0c;与其脱离不了干系&#xff0c;即使在分页机制下的进程也要先经过逻辑上的分段才行&#xff0c;每加载一个进程&#xff0c;操作系统按照进程中各段的起始范围&#xff0c;在进程自己的4GB虚拟地址空间中寻找可有空间…

PointNet:3D点集分类与分割深度学习模型

之前的一篇博客《动手学无人驾驶&#xff08;4&#xff09;&#xff1a;基于激光雷达点云数据3D目标检测》里介绍到了如何基于PointRCNN模型来进行3D目标检测&#xff0c;作者使用的主干网是PointNet&#xff0c;而PointNet又是基于PointNet来实现的。今天写的这篇博客就是对Po…

【POJ - 3281】Dining(拆点建图,网络流最大流)

题干&#xff1a; Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others. Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although…