Java中基类构造函数调用重写方法时派生类对象的状态 [英] State of Derived class object when Base class constructor calls overridden method in Java

查看:29
本文介绍了Java中基类构造函数调用重写方法时派生类对象的状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请参考下面的Java代码:

Please refer to the Java code below:

class Base{
     Base(){
         System.out.println("Base Constructor");
         method();
     }
     void method(){}    
}

class Derived extends Base{
    int var = 2;
    Derived(){
         System.out.println("Derived Constructor");  
    }

     @Override
     void method(){
        System.out.println("var = "+var);
     }
 }

class Test2{
    public static void main(String[] args) {
        Derived b = new Derived();
    }
}

看到的输出是:

Base Constructor
var = 0
Derived Constructor

我认为 var = 0 的发生是因为派生对象初始化了一半;类似于Jon Skeet 在这里所说的

I think var = 0 occurs because Derived object is half initialized; similar to what Jon Skeet says here

我的问题是:

如果 Derived 类对象尚未创建,为什么会调用重写的方法?

Why does the overridden method get called if the Derived class object isn't created yet?

var 在什么时间点被赋值为 0?

At what point in time is var assigned value 0?

是否有需要这种行为的用例?

Are there any use cases where such behavior is desired?

推荐答案

  • Derived 对象已经被创建——只是构造函数还没有运行.在 Java 中,对象的类型在它被创建的那一刻之后永远不会改变,这发生在所有构造函数运行之前.

    • The Derived object has been created - it's just that the constructor hasn't been run yet. The type of an object never changes in Java after the instant it is created, which happens before all constructors run.

      var 作为创建对象过程的一部分被分配了默认值 0.基本上,类型引用被设置,代表对象的其余内存被擦除为零(无论如何,从概念上讲 - 它可能之前已经被擦除为零,作为垃圾收集的一部分)

      var is assigned the default value of 0 as part of the process of creating an object, before constructors are run. Basically, the type reference gets set and the rest of the memory representing the object gets wiped to zero (conceptually, anyway - it may already have been wiped to zero before, as part of garbage collection)

      这种行为至少会导致一致性,但可能会很痛苦.在一致性方面,假设您有一个可变基类的只读子类.基类可能有一个 isMutable() 属性,该属性实际上默认为 true - 但子类覆盖它以始终返回 false.对象在子类构造函数运行之前是可变的,但之后是不可变的,这会很奇怪.另一方面,在类的构造函数运行之前,在类中运行代码的情况肯定很奇怪:(

      This behaviour at least leads to consistency, but it can be a pain. In terms of consistency, suppose you had a read-only subclass of a mutable base class. The base class may have an isMutable() property which was effectively defaulted to true - but the subclass overrode it to always return false. It would be odd for the object to be mutable before the subclass constructor ran, but immutable afterwards. On the other hand, it's definitely strange in situations where you end up running code in a class before the constructor for that class has run :(

      一些准则:

      • 尽量不要在构造函数中做太多工作.避免这种情况的一种方法是在静态方法中工作,然后使静态方法的最后部分成为构造函数调用,该调用仅设置字段.当然,这意味着您在工作时不会获得多态的好处 - 但无论如何在构造函数调用中这样做都是危险的.

      • Try not to do much work in a constructor. One way of avoiding this is to do work in a static method, and then make the final part of the static method a constructor call which simply sets fields. Of course, this means you won't get the benefits of polymorphism while you're doing the work - but doing so in a constructor call would be dangerous anyway.

      尽量避免在构造函数期间调用非 final 方法 - 这很可能导致混淆.记录任何方法调用,您确实必须非常非常,以便覆盖它们的任何人都知道它们将在初始化完成之前被调用.

      Try very hard to avoid calls to non-final methods during a constructor - it's very likely to cause confusion. Document any method calls you really have to make very clearly, so that anyone overriding them knows that they will be called before initialization has finished.

      如果你必须在构造过程中调用一个方法,那么通常之后调用它是不合适的.如果是这种情况,请将其记录下来并尝试在名称中指明.

      If you have to call a method during construction, it's usually not then appropriate to call it afterwards. If that's the case, document it and attempt to indicate it in the name.

      首先尽量不要过度使用继承 - 只有当您的子类从 Object 以外的超类派生时,这才会成为一个问题:) 设计继承很棘手.

      Try not to overuse inheritance in the first place - this is only going to become an issue when you've got a subclass deriving from a superclass other than Object :) Designing for inheritance is tricky.

      这篇关于Java中基类构造函数调用重写方法时派生类对象的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆