我刚开始学习Java。我明白了
但是我被困在一个代码中,我已经多态地调用了一个实例变量,但它显示了重写值(它不应该显示)。在子类'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:当它为最后一个案例显示子类'变量的值时,为什么不为这种情况。答案 0 :(得分:2)
为什么显示“35”,它应显示超类'变量的值为50。
在Child
类中初始化变量age
之后,子类Parent
的初始化块执行。因此,age
首先初始化为50
,然后初始化为35
。
Java语言规范Section 12.5 on Creation of New Class Instances中对此进行了详细解释,相关部分以粗体显示:
在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:
将构造函数的参数分配给此构造函数调用的新创建的参数变量。
如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7.1节)开头(使用
this
),则评估参数并使用这些构造函数递归地处理该构造函数调用五个步骤。如果该构造函数调用突然完成,则此过程突然完成,原因相同;否则,继续步骤5.此构造函数不是以同一个类中的另一个构造函数的显式构造函数调用开始的(使用
this
)。 如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super
)。使用这五个相同的步骤评估参数并递归处理超类构造函数调用。如果该构造函数调用突然完成,则此过程突然完成,原因相同。否则,请继续执行步骤4.为此类执行实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值分配给相应的实例变量,按从而出现的从左到右的顺序在文本的源代码中。如果执行任何这些初始值设定项导致异常,则不会处理其他初始化程序,并且此过程会突然完成同样的异常。否则,请继续步骤5.
- 醇>
执行此构造函数的其余部分。如果执行突然完成,则此过程突然完成,原因相同。否则,此过程正常完成。
关于第二个问题,referToChildTwo
声明为Parent
,而其实际类型为ChildTwo
。 ChildTwo
个实例有两个age
字段,一个在ChildTwo
中定义,另一个从Parent
继承。
当您编写表达式referToChildTwo.age
时,将评估Parent
中继承的字段。要评估子类中定义的那个,您需要转换变量,即((ChildTwo)referToChildTwo).age
。
答案 1 :(得分:1)
它不能被覆盖,但它由子类继承,只要它在父类中不是私有的。他们可以访问它,包括阅读和写作。
重写是创建一个新成员,它是当前类的一部分,它具有与父类成员相同的定义,并且当您以多态方式使用该对象时,将访问该成员。
例如:
class Parent {
public int age = 50;
}
class Child {
public int age = 80;
}
我们在这里定义了一个新成员age
,该成员与父成员age
分开。如果您使用Child
从this.age
内部访问它,则会获得80
。如果您使用age
访问父级super.age
,则会获得50
。
但这不是重写,因为如果您以多态方式使用该对象,它将访问父age
:
Child childObj = new Child();
Parent parentObj = childObj;
System.out.println( childObj.age ); // Will print 80
System.out.println( parentObj.age ); // Will print 50
尽管事实上它们都是同一个对象。这是因为孩子隐藏字段而不是覆盖。
简单地在从父级继承的字段中指定值不会覆盖。它是继承的一部分。