`

Object类是如何成为默认父类的

    博客分类:
  • java
阅读更多

经常有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类的publicprotected资源,如toString方法。那么Java编译器和JVM到底是如何做的呢?

了解这个原因其实并不需要知道JVM的实现细节。只要思考一下对于这种虚拟机程序的原理即可。一般对于这种靠虚拟机运行的语言(如JavaC#等)会有两种方法处理默认继承问题。

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,图1Test.class的十六进制代码:

大家可以看到,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 Object类认识

    在Java编程语言中,`Object`类是所有类的根,每个自定义类如果没有明确指定父类,都默认继承自`Object`。因此,对`Object`类的理解是每个Java开发者的基本功。本文将深入探讨`Object`类,以及其核心方法`equals()`与...

    Java面向对象(进阶)- Object类的详细概述

    Object类是所有Java类的根父类,无论何时我们创建一个新的类,除非明确指定其他父类,否则它都会默认继承Object类。这使得Object类中的方法对所有Java类都可用,体现了Java的继承性和多态性。 1. **根父类理解** -...

    Java程序设计:020611_Object类.ppt

    在Java编程语言中,Object类是一个非常基础且重要的类,它是所有类的终极父类。这意味着,无论我们自定义的类是否显式声明了继承,它们实际上都是Object类的间接子类。`Java程序设计:020611_Object类.ppt`这个资料...

    接口与Object类

    Object类在Java中具有举足轻重的地位,它是所有类的直接或间接父类。这意味着每一个自定义类,默认情况下都是Object类的子类,即使没有显式声明也继承了Object类的所有属性和方法。 #### toString() 方法 `...

    java反射获取所有属性,获取所有get方法,包括子类父类

    `getDeclaredFields()` 返回的是类声明的所有字段,不包括继承自父类的字段。如果想获取包括父类在内的所有属性,需要递归遍历父类: ```java void printAllFields(Class&lt;?&gt; clazz) { Field[] fields = clazz....

    Java基础知识-day01【Object类、常用API】.pdf

    不论你定义的类是否显式声明父类,都会默认继承Object类。Object类提供了处理对象通用的方法。 - **toString()**:返回对象的字符串表示。默认实现返回类名加@符号后跟对象的内存地址。通常我们需要重写此方法,...

    Object类常用方法(csdn)————程序.pdf

    Object 类是 Java 语言中的顶层类,是所有类的直接或间接父类。任何类,如果没有书写 extends 显式继承某个类,都默认直接继承 Object 类,否则为间接继承。Object 类中所定义的方法,是所有对象都具备的方法。 ...

    Java Object实例代码

    `Object`类是所有类的父类,因此,当我们自定义类时,除非显式声明其他父类,否则默认继承`Object`。多态性是面向对象编程的重要特性,允许我们用父类引用指向子类对象,实现代码的灵活性和可扩展性。例如,可以...

    第十二天 04单继承:子类只继承一个父类【千锋Python人工智能学院】1

    在Python 3.x中,所有类默认都继承自`object`,因此都是新式类。但在Python 2.x中,若未显式指定继承`object`,则不是新式类。为了保证兼容性,建议在Python 2.x中定义类时,即使没有父类,也明确指定继承`object`:...

    java中的继承(子类调用父类构造方法还不懂).doc

    继承允许创建一个新的类(称为子类或派生类),该类继承了现有类(称为父类或基类)的所有属性和行为。通过继承,子类不仅可以重用父类的功能,还可以扩展或覆盖父类的行为。 #### 二、子类如何调用父类构造方法 ...

    java中object类实例分析

    Object类是Java语言中所有类的父类,位于java.lang包中。它是所有Java类的终极父类,数组也继承了Object类。然而,接口是不继承Object类的,Object类不作为接口的父类。 Object类提供了几个重要的方法,包括equals...

    Java中父类Object的常用方法总结

    Java中的`Object`类是所有Java类的根父类,每个自定义的类如果没有明确指定父类,那么它默认就会继承`Object`类。本文将详细介绍`Object`类中的三个重要方法:`toString()`、`equals()`和`hashCode()`。 **1. `...

    第8章 内部类和Object.docx

    }}在 ModifierTest2 类中,由于它继承了 ModifierTest1,所以它可以访问所有父类的变量,但 private 变量 privVar 由于私有化,所以无法直接访问,尝试访问会抛出异常。 2. Object 类(了解)Object 类是 Java 中...

    Java实训教程 Java软件开发实战 Java类库 第1章 Object类 共29页.pptx

    - 如果一个类没有显式地指定父类,则默认继承自`Object`类。 - 由于`Object`类的特殊地位,一个`Object`类型的变量可以引用任何对象,包括各种类型的对象和数组等。 **2. `Object`类的方法** `Object`类定义了一...

    JAVA入门-Object类、Class类

    总的来说,Object类和Class类是Java语言的基础构建块,理解它们的工作原理对于成为一名熟练的Java开发者至关重要。在编程实践中,经常会遇到需要重写`equals()`和`toString()`的情况,以及利用Class对象进行反射操作...

    EnumTest--构造顺序:父类、类成员变量、子类.zip

    但如果是类实例的成员变量,其析构顺序会是子类的清理逻辑、类成员变量的清理,最后是父类的清理逻辑,因为这些清理动作是伴随着对象被垃圾回收而发生的。 标签"构造函数"强调了这个话题的核心,即构造过程中类实例...

    objectJava8

    在Java编程语言中,Object类是所有类的父类,它提供了所有对象共有的基本方法。在Java 8中,Object类得到了一些新的特性增强,这些改进使得Java开发者在处理对象时有了更多的灵活性和效率。本文将深入探讨Java 8中...

    java自己修改的支持public属性、父类属性的json自动编译的工具类

    针对你的需求,我们讨论一个自定义的工具类,它支持处理具有public属性以及父类属性的JSON对象,并利用反射机制进行操作。这个工具类名为`JsonUtil`,以下是关于这个工具类及其涉及知识点的详细说明: 1. **public...

    最完整的Object Pascal语言介绍

    Object Pascal是一种基于Pascal编程语言的面向对象的扩展版本,它在传统的Pascal基础上引入了类、对象、接口等概念,极大地增强了其灵活性和可扩展性。本篇将深入探讨Object Pascal语言的核心特性、语法结构以及在...

Global site tag (gtag.js) - Google Analytics