经常有Java初学者会问为什么一个没有父类的Java类会自动从java.lang.Object类继承。如下面是一个普通的Java类:

public class Test    // 从Object类继承
{
    public static void main(String[] args)
    {
        System.out.println(new Test().toString());
    }
}
从上面的代码可以看出,实际上,Test类的父类就是Object,因此,在Test中可以使用Object类的public或protected资源,如toString方法。那么Java编译器和JVM到底是如何做的呢?
了解这个原因其实并不需要知道JVM的实现细节。只要思考一下对于这种虚拟机程序的原理即可。一般对于这种靠虚拟机运行的语言(如Java、C#等)会有两种方法处理默认继承问题。
1. 在编译源代码时,当遇到没有父类的类时,编译器会将其指定一个默认的父类(一般为Object),而虚拟机在处理到这个类时,由于这个类已经有一个默认的父类了,因此,VM仍然会按着常规的方法来处理每一个类。对于这种情况,从编译后的二进制角度来看,所有的类都会有一个父类。
2. 编译器仍然按着实际代码进行编译,并不会做额外的处理。如果一个类没有显式地继承于其他的类,编译后的代码仍然没有父类。然后由虚拟机运行二进制代码时,当遇到没有父类的类时,就会自动将这个类看成是Object类的子类(一般这类语言的默认父类都是Object)。
从上面两种情况可以看出,第1种情况是在编译器上做的文章,也就是说,当没有父类时,由编译器在编译时自动为其指定一个父类。第2种情况是在虚拟机上做文章,也就是这个默认的父类是由虚拟机来添加的。那么Java是属性哪一种情况呢?其实这个答案很好得出。只需要随便找一个反编译工具,并.class文件进行反编译即可得知编译器是如何编译的。就以上面代码为例,如果是第1种情况,就算Test没有父类,但由于编译器已经为Test自动添加了一个Object父类,因此,在反编译后得到的源代码中的Test类是从Object类继承的。如果没是这种情况,那么就是第2种情况。
现在我们使用JDK带的反编译工具javap来反编译Test.class,先执行下面的命令:
javap Test > Test.txt

打开Test.txt文件后,会看到如下的代码:

public class Test extends java.lang.Object{
    public Test();
    public static void main(java.lang.String[]);
}
再使用下面的命令来得到bytecode代码:
javap -c Test >Test1.txt

打开Test1.txt后,会看到如下的代码:

public class Test extends java.lang.Object{
public Test();
  Code:
   0:    aload_0
   1:    invokespecial    #8; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    getstatic    #16; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:    new    #1; //class Test
   6:    dup
   7:    invokespecial    #22; //Method "<init>":()V
   10:    invokevirtual    #23; //Method java/lang/Object.toString:()Ljava/lang/String;
   13:    invokevirtual    #27; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   16:    return
}

从上面两段代码可以看出,Test已经从Object继承了,因此,可以断定Java是属性第1种情况,也就是说由编译器为没有父类的类指定了Object作为其默认父类。如果读者还不确定,可以直接打开Test.class,看看里面有没有Object,图1是Test.class的十六进制代码:

图1

大家可以看到,Java编译器已经为Test指定了一个默认的Object类作为其父类。目前大多数基于虚拟器的语言都是采用的第1种方法来处理默认父类的,如下面的C#代码:

using System;

namespace ConsoleApplication1
{
    class Test
    {
        static void Main(string[] args)
        {
            Console.WriteLine(new Test().ToString());
        }
    }
}

使用ildasm.exe将上面的代码反编译后,得到的MSIL代码如下:

.class private auto ansi beforefieldinit ConsoleApplication1.Test
       extends [mscorlib]System.Object
{
} // end of class ConsoleApplication1.Test

从上面的代码可以清楚地看到,Test类已经有一个System.Object作为父类了。

java.lang.Object是如何成为默认父类的相关推荐

  1. java.lang.object 下载_java.lang.Object

    java.lang.Object 类Object是类层次结构的根类.每个类都使用Object作为超类. 所有对象(包括数组)都实现这个类的方法. Object是根父类,如何理解? (一)从继承 (1) ...

  2. ArrayMap java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]

    错误堆栈: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]at android. ...

  3. The type java.lang.Object cannot be resolved

    java常见异常 @(JAVA)[java] 1.The type java.lang.Object cannot be resolved The type java.lang.Object cann ...

  4. 【典型错误】The type java.lang.Object cannot be resolved.

    参考:http://blog.csdn.net/wo519074786/article/details/7697967 The type java.lang.Object cannot be reso ...

  5. eclipse java转class_Eclipse中的Java项目:无法解析java.lang.Object类型。 它是从所需的.class文件间接引用的...

    Eclipse中的Java项目:无法解析java.lang.Object类型. 它是从所需的.class文件间接引用的 在Eclipse中导入项目后,我收到以下错误: 无法解析java.lang.Ob ...

  6. 【Java】java.lang.Object

    文章目录 java.lang.Object核心要点 java.lang.Object重要方法 java.lang.Object核心要点 Object类是所有类的基类,是Java中唯一一个没有基类的类. ...

  7. InvalidDefinitionException: No serializer found for class java.lang.Object and no properties discove

    使用springcloudgateway 搭建项目后,写个test验证返回响应,响应结果报如下错误: {"timestamp": "2022-04-08T14:21:45 ...

  8. java项目导入jre不识别_Eclipse中的Java项目:无法解析类型java.lang.Object。 从所需的.class文件间接引用它...

    在Eclipse中导入项目后出现以下错误: The type java.lang.Object cannot be resolved. It is indirectly referenced from ...

  9. The type java.lang.Object cannot be resolved It is indirectly referenced ... .

    The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files ...

最新文章

  1. linux企业常用命令必之必会二
  2. 一个App完成入门篇(一)-从Hello world开始
  3. [转] Java多线程发展简史
  4. Webstorm 10.0.4 配置
  5. 分数化小数 Fractions to Decimals
  6. JavaSE 基础面试题
  7. python 生成排列、组合以及选择
  8. PCB-电解电容的封装
  9. gt爵士变形步骤_代码广播简介:您可以编码为24/7的爵士节拍
  10. 客户端(前端)Ajax中Get请求和Post请求的区别
  11. bzoj 3385: [Usaco2004 Nov]Lake Counting 数池塘(DFS)
  12. [死亡笔记]某傻逼的错误实况
  13. 《模式识别与机器学习》 简称 PRML 开源了
  14. 中小企业选择仓库管理软件免费版的七大特点
  15. 怎么把外部参照合并到图纸_CAD外部参照如何绑定?
  16. 朴素贝叶斯——新闻分类
  17. 简单好听的id_简单好听的微信id(精选500个)_见过的最好看的微信id_简单好记好看的微信号 - 第5页...
  18. 常用正则表达式大全 (转)
  19. Es6类数组length属性和扩展方法,find(),findIndex(),fill(),copyWithin(),entries()...用法
  20. 01前端入门HTML5 +Css3+电商网页制作:HTML5

热门文章

  1. 《信息存储与管理(第二版):数字信息的存储、管理和保护》—— 2.6 磁盘驱动部件...
  2. Yii2数据库操作的各种写法
  3. ip对应的区域查询(asp.net版)
  4. latex algorithm 引用格式错误
  5. 【0702作业】输出九九乘法表
  6. js字符串常用方法详解
  7. Java_基础(一)
  8. Linux_shell 学习
  9. Border Layout
  10. VMware View 要求操作句柄的状态错误