java - 实例变量,当在子类的初始化 block 中重新初始化时,像实例方法一样被覆盖,它不应该

标签 java inheritance polymorphism

刚开始学Java,我懂

  1. 与实例方法不同,实例变量不能被覆盖,并且在运行时以多态方式访问时不会由 JVM 动态选择。
  2. 执行流程:静态 block 、 super 构造函数、初始化 block ,然后是构造函数。

但我被困在一个代码中,我在其中以多态方式调用了一个实例变量,但它显示了被覆盖的值(它不应该显示)。实例变量在子类的 init block 中被覆盖。

package package1;

public class Other {
    
    public static void main(String [] args){
            Parent referToChild = new Child();
            Parent referToChildTwo = new ChildTwo();
            System.out.println("age as referred by referToChild reference variable is:" + referToChild.age);// prints 35 (doubt 1)
            System.out.println("age as referred by referToChildTwo reference variable is:" + referToChildTwo.age);// prints 50 (doubt 2)
            System.out.println("money as referred by Other reference variable is:" + referToChild.money);
            //System.out.println("Other reference variable is:" + othObj.age);
    }
}

class Child extends Parent{
    // init block 
    {
        age = 35;
    }
}

class ChildTwo extends Parent{
    public int age;
    {
        age = 40;
    }
}

class Parent{
     public int age = 50;
     public int money = 100;
}

我得到的答案是:

35

50

100

所以我的疑惑是:

疑问1:为什么显示“35”,应该显示父类的变量值50。

疑点2:最后一个case显示的是子类的变量值,为什么不显示这个case。

最佳答案

Why is it showing "35", it should display super class' variable's value which is 50.

子类Child 的初始化程序 block 变量ageParent 类中初始化后执行。因此,age首先被初始化为50,然后是35

这在 Java 语言规范中有非常详细的解释 Section 12.5 on Creation of New Class Instances ,相关部分以粗体显示:

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

对于第二个问题,referToChildTwo声明的类型是Parent,而它的实际类型是ChildTwo。一个 ChildTwo 实例有两个 age 字段,一个定义在 ChildTwo 中,另一个继承自 Parent

当您编写表达式 referToChildTwo.age 时,将评估 Parent 中继承的字段。要评估子类中定义的变量,您需要转换变量,即 ((ChildTwo)referToChildTwo).age

关于java - 实例变量,当在子类的初始化 block 中重新初始化时,像实例方法一样被覆盖,它不应该,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28517812/

相关文章:

inheritance - 在 Kotlin 中扩展 Java 类时继承的平台声明冲突

Objective-C 协议(protocol)模仿 'virtual-functions' 会产生编译器警告?

java - 可在 while 循环中运行

java - 为什么我会遇到类强制转换异常?安卓

c++ - 如何在虚拟继承下游使用参数化基类构造函数

scala - 如何在scala中获得通用(多态)lambda?

java - 动态绑定(bind) == 是否在 Java 中进行后期绑定(bind)?

java - BigInteger.isProbablePrime

java - 命名查询和继承

c# - 继承 : does not contain a definition for and no extension method accepting a first argument