【问题标题】:When is an Object created after a constructor is called调用构造函数后何时创建对象
【发布时间】:2012-02-21 17:14:22
【问题描述】:

考虑以下代码类。




     public class A
    {
        public A()
        {
            callCreation();
        }

        protected void callCreation()
        {
            System.out.println("A Created!!");
        }
    }




    public class B extends A
    {
        protected void callCreation()
        {
            System.out.println("B Created!!");
        }
    }


    public class C extends B
    {
        protected void callCreation()
        {
            System.out.println("C Created!!");
        }

        public static void main(String[] args)
        {
            A a = new A();
            A b = new B();
            A c = new C();
        }
    }

运行C类的输出如下。

一个创造!! B创建!! C创建!!

输出中的第一行输出

A Created!!
被打印是因为在调用类 A 的构造函数时,它在调用类 A 的构造函数中的 callCreation() 方法之前隐式调用了超类的构造函数 (java.lang.Object)。 B 类和 C 类也是如此。在这种情况下,当调用 B 的构造函数时,调用流程通常应该是:B 的构造函数 -> A 的构造函数 -> java.lang.Object 的构造函数 -> 回到 A 的 callCreation() 方法以完成调用 A 的构造函数。如果是这样,如何打印覆盖的值而不是打印超类的值?所以问题是'什么时候准确地创建了一个类的对象?换句话说,只有在构造函数完成调用/初始化其自身的所有元素之后,才能创建类的对象。如果是这样,如何从子类而不是父类调用方法?

【问题讨论】:

    标签: java object constructor creation


    【解决方案1】:

    B 和 C 中的 callCreation 方法覆盖 A 中的方法。因此,当在构造函数 A 中调用该方法时,将运行 B 和 C 中的实现,即使B 和 C 还没有被执行。这是可能的,因为构造函数实际上并不创建对象,而是在 JVM 创建对象之后的某个时刻调用它们来初始化

    通常,出于这个原因,调用可以从构造函数中覆盖的方法是一个非常糟糕的主意。 B 或 C 中的方法可能假定构造函数和对象初始化程序已运行,并从字段中读取意外值。例如,以下内容最终会打印 "B Created!! null",因为该字段仍未被分配其值。

    public class B extends A
    {
        final String msg = "Yes!";
    
        protected void callCreation()
        {
            System.out.println("B Created!! "+msg);
        }
    }
    

    【讨论】:

    • +1 完全正确 - 它总是从同一个构造函数中调用。唯一的区别是呼叫的去向。
    • jvm不需要一个对象来调用它的方法吗?请在下面的答案中找到我的评论。
    • 是的;事实上,它还需要一个对象来运行构造函数。该对象在构造函数执行之前很久就存在了。
    • 我在这里有点困惑。对象在构造之前怎么存在?
    • “构造函数”一词具有误导性。实际上,它们只是在 JVM 创建对象后不久调用的特殊方法。
    【解决方案2】:

    以这种方式思考会让事情变得更明显: 当创建 B 类型的对象时, super() 关键字调用 A 构造函数, 然后在A构造函数中执行“this.callCreation()”,它指的是当前 对象是B,所以调用与当前对象(B)对应的callCreation。 对 C 执行相同的过程。

    公开课 A {

    public A() {
        this.callCreation();
    }
    
    protected void callCreation() {
        System.out.println("A Created!!");
    }
    

    }

    B 类扩展 A {

    public B() {
        super();
    }
    
    protected void callCreation() {
        System.out.println("B Created!!");
    }
    

    }

    C 类扩展 B {

    public C() {
        super();
    }
    
    protected void callCreation() {
        System.out.println("C Created!!");
    }
    
    public static void main(String[] args) {
    
           A a = new A();
           A b = new B();
           A c = new C();
    
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2019-07-25
      • 2013-03-07
      • 2013-09-24
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      相关资源
      最近更新 更多