本文介绍了由于java中的继承,创建了多少个对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有三个班级:

class A {
    A() {
        // super();
        System.out.println("class A");
    }
}
class B extends A {
    B() {
        // super();
        System.out.println("class B");
    }
}
class C extends B {
    public static void main(String args[]) {
        C c = new C(); //Parent constructor will get called
    }
}

当我创建类 C 的实例时,它会调用超类的构造函数.那么,是否有不止一个对象被创建?如果只创建一个对象,那么 super() 与另一个类的构造函数有何相似之处?super() 方法是否在内部创建对象?我所知道的是,构造函数也是一个方法(我可能错了).

When I create an instance of class C, it calls the constructor of super class. So, is there more than one object that is getting created? If only one object is created, then how is super() like another class' constructor? Does super() method internally create an object? What I know is, the constructor is also a method (I may be wrong).

我的问题是:

  1. 在这种情况下创建了多少个对象?
  2. 如果创建了一个对象,那么 Super() 如何在内部调用父类构造函数?

推荐答案

很好的问题.您正在探索的是 Java 如何初始化对象 - 涉及到许多步骤.

Great question. What you are probing is how Java initializes objects - and there are a number of steps involved.

我知道构造函数也是一种方法(也许我错了).

几乎正确.构造函数是一种特殊的方法.如果你反编译一个类文件,你会看到构造函数被重命名为 . 与其他方法的处理方式不同,例如,不能显式调用,除非使用关键字 newsuper>.这是非常基础的,它是在 JVM 本身中实现的,而不是在 Java 语言中定义的.

Nearly right. The Constructor is a special method. If you decompile a class file, you'll see the constructors get renamed to <init>. <init> is treated differently from other methods and, for example, can't be called explicitly except through use of the keyword new or super. This is so fundamental that it is implemented in the JVM itself rather than being something defined in the Java language.

在这种情况下创建了多少个对象.

创建了一个对象 - C 的一个实例.

One object is created - an instance of C.

C 又是一个 B 的实例和一个 A 的实例,同时也是 Object 的一个实例.

C is additionally and simultaneously an instance of B and an instance of A and also Object.

如果创建了一个对象,那么 super() 在内部如何调用父类 Constructor .Super 如何调用父类构造函数.

这是我们进入初始化的地方 - 初始化是 JVM 创建对象的新实例并设置所有成员值的方式 - 特定类的值和超类的值.涉及几个阶段:

This is where we get into initialization - initialization is how the JVM creates a new instance of an object and sets all the member values - those of the specific class and those of the superclasses. There are several stages involved:

  • 加载所有引用的类并初始化这些类.类初始化本身很重要,所以我不会在这里介绍.值得一读.
  • 为实例的成员分配一块内存,其中将包括ABC的所有成员.注意 这解释了您问题的一个方面:基类及其子类的构造函数如何更新或引用同一个对象 - 所有类的实例的所有成员都存储一个在同一块内存中的另一个之后.
  • 将所有成员初始化为其默认值.例如,intfloat 成员将被设置为 0 和 0.0f.
  • 执行或计算成员初始值设定项,例如:

  • Load all the referenced classes and initialize those classes. Class initialization is itself non-trivial so I won't cover it here. It is well worth reading up.
  • Allocate a chunk of memory for holding the members of the instance, which will include the all members of A, B and C. NOTE this explains one aspect of your question: how can the constructors of the base class and its subclasses update or refer to the same object - all the members of the instance from all classes are stored one after the other in the same chunk of memory.
  • Initialize all the members to their default value. For example, int and float members will be set to 0 and 0.0f.
  • Execute or calculate the member initializers, eg:

private int a = 10;
private int b = a * 5;
private String c = Singleton.getInstance().getValue();

  • 注意 (1) 成员初始化严格按照成员在类中声明的顺序进行.这意味着声明后面对成员的引用被破坏了:

  • Note (1) that member initialization occurs strictly in the order that members are declared in the class. This means that references to members later in the declaration are broken:

    private int a = b * 5; // Forward reference; won't compile
    private int b = 10;
    

  • 注意 (2) Java 中有一个未充分利用的工具,可以在执行构造函数之前运行任意代码来初始化值.这些代码块此时再次严格按照声明的顺序执行:

  • Note (2) that there is a under-used facility in Java to run arbitrary code to initialize values before the constructor is executed. These code blocks are executed at this time again strictly in order of declaration:

    private int a;
    private int b = 1;
    {
        // Initization occurs after b but before c.
        // c cannot be referenced here at all
        int i = SomeClass.getSomeStatic();
        a = i * 2;
    }
    private int c = 99;
    

  • 执行C的构造函数.构造函数必须直接从超类调用构造函数,否则编译器会自动添加 super() 作为构造函数的第一行.这意味着构造函数严格按顺序执行:

  • Execute the constructor of C. Constructors must either directly invoke a constructor from the superclass or the compiler will automatically add super() as the first line of the constructor. This means that the constructors are strictly executed in order:

    1. 对象
    2. A
    3. B
    4. C

  • 对象现在已初始化并可使用.如果您使用实例方法初始化值,您可能会做一些危险的事情:

    The object is now initialized and is ready for use. You can do some dangerous stuff if you initialize value using instance methods:

    public class Wrong {
        int a = getB(); // Don't do this!
        int b = 10;
        public int getB() {
             return b;
        }
    }
    

    这里,a被初始化为0.这是因为,在调用 getB() 时,Java 已将 b 的值清除为默认值 (0),但是尚未在初始化的第二阶段将其设置为 10.

    Here, a is initialized to 0. This is because, at the point getB() is invoked, Java has cleared the value of b to the default (0), but has not yet set it to 10 in the second phase of initialization.

    总而言之 - 只有一个对象,它是分阶段创建和初始化的.在这些阶段,根据定义,对象并没有完全定义.

    In summary - there is only one object and it is created and initialized in a number in stages. During those stages, the object is, by definition, not completely defined.

    这篇关于由于java中的继承,创建了多少个对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-14 16:10