class Parent{
int x=10;
public Parent(){
add(2);
}
void add(int y){
x+=y;
}
}
class Child extends Parent{
int x=9;
void add(int y){
x+=y;
}
public static void main(String[] args){
Parent p=new Child();
System.out.println(p.x);
}
}
问输出结果是什么?
答案应该是10。
要理解结果为什么是10,需要首先明白下面的知识:
(1)方法和变量在继承时的隐藏与覆盖
隐藏:若B隐藏了A的变量或方法,那么B不能访问A被隐藏的变量或方法,但将B转换成A后可以访问A被隐藏的变量或者方法。
覆盖:若B覆盖了A的变量或者方法,那么不仅B不能访问A被覆盖的变量或者方法,将B转换成A后同样不能访问A被覆盖的变量或者方法。
(2)Java中变量与方法在继承中的隐藏与覆盖规则:
一、父类的实例变量和类变量能被子类的同名变量隐藏。
二、父类的静态方法被子类的同名静态方法隐藏,父类的实例方法被子类的同名实例方法覆盖。
三、不能用子类的静态方法隐藏父类的实例方法,也不能用子类的实例方法覆盖父类的静态方法,否则编译器会异常。
四、用final关键字修饰的最终方法不能被覆盖。
五、变量只能被隐藏不会被覆盖,子类的实例变量可以隐藏父类的类变量,子类的类变量也可以隐藏父类的实例变量。
在上面的试题中,子类Child的实例方法add(int y)覆盖了父类Parent的实例方法add(int y),而子类的实例变量x则是隐藏了父类的实例变量x。
Child对象的初始化过程是:
首先为父类的实例变量x分配内存空间,因为在定义变量x时为它赋了值(int x=10),所以会同时将这个值赋给x。
其次调用父类的无参构造函数,Parent的构造函数中做的唯一的事情就是调用了add(2);
第三、由于子类的add(int y)方法覆盖了父类的方法,所以add(2)实际调用的是子类的方法,在子类的add方法中做了如下操作x+=j;在这里由于子类的实例变量x隐藏了父类 的实例变量x,所以这条语句是针对子类本身的,但是这时还没有为子类的实力变量x分配空间,它的默认值是0,加2之后是2。
第四、父类初始化完毕后接着初始化子类,为子类的x分配内存空间并将它赋值为9,之前的add(2)操作白瞎了。
再次注意Parent p=new Child();这条语句,它是用父类的引用指向子类的对象,而前面已经说过变量只会被隐藏不会被覆盖,所以这时的p.x值应该是父类的10,而不是子类的9;
如果将输出语句换成下面的语句结果就是9了:
System.out..println(((Child)p).x); //首先将p转换成Child类型
分享到:
相关推荐
"C++ 子类构造函数初始化及父类构造初始化的使用" C++ 中的构造函数初始化是指在类对象创建时对其进行初始化的过程。构造函数是类的特殊成员函数,用于初始化类对象。在 C++ 中,子类构造函数的初始化涉及到父类...
综上所述,程序执行顺序的基本原则是:首先初始化并执行父类的构造器、静态和实例初始化块,然后执行子类的构造器、实例初始化块。最后,当通过子类对象调用方法时,优先执行子类覆盖的方法。理解这一顺序对于编写可...
java 静态_非静态 字段_方法_代码块 子类父类构造_初始化顺序! 三个class 让你清清楚楚 第一个class java代码如下: package initialOrder; class Parent { // 静态变量 public static String p_StaticField...
如果子类没有定义自己的构造函数(即没有定义`__init__`方法),那么在实例化子类时,Python会自动调用父类的构造函数来初始化对象。例如: ```python class Son(Father): def getName(self): return 'Son' + ...
在Windows Presentation Foundation (WPF) 中,继承是面向对象编程的一个关键特性,它允许子类继承父类的属性、字段和方法,以便扩展或重写它们。标题“WPF继承_子类继承父类,实现跨类调用方法”表明我们将讨论如何...
2. **构造器与初始化**:子类对象在创建时会先调用父类的构造器,确保父类的状态得到正确初始化,然后执行子类自己的构造逻辑。 3. **变量隐藏**:如果子类和父类有同名的实例变量,子类变量会“隐藏”父类变量。...
在Python的面向对象编程中,当我们创建一个...理解并正确使用父类初始化在Python的面向对象编程中至关重要,因为它确保了代码的可扩展性和复用性。通过子类调用父类的初始化,我们可以构建更加灵活和模块化的程序结构。
NULL 博文链接:https://happywaterlife.iteye.com/blog/1567461
本文实例讲述了Python实现...子类不显式调用父类的构造方法,而父类构造函数初始化了一些属性,就会出现问题 如果子类和父类都有构造函数,子类其实是重写了父类的构造函数,如果不显式调用父类构造函数,父类的构造
当需要将父类的对象赋值给子类的对象时,通常的目标是保留父类的所有属性值,并可能在子类中初始化额外的属性。有几种方法可以实现这一点: 1. **构造函数参数**: 子类的构造函数可以接受一个父类对象作为参数,...
这样可以实现父类的初始化,并在子类中实现对父类成员变量的访问和操作。 在实际应用中,C++类继承可以广泛应用于各种领域,如网络编程、数据库编程、图形编程等。通过继承,可以实现代码的重用和模块化,提高编程...
这对于初始化父类的状态非常有用。 - **追溯父类**:`super`不仅可以用于直接父类,还可以追溯到更远的祖先类。 **2. 调用父类构造器的语法** 在子类的构造方法中,可以使用以下语法调用父类的构造方法: ```java...
而`引用`则是一种别名,一旦初始化后,它总是代表同一个对象。引用不是独立的内存单元,而是现有对象的另一个名字,它比指针更安全,使用起来也更直观。 接下来,我们讨论`虚函数`。在C++中,虚函数允许子类重写...
构造方法负责创建`classes`数组(初始为空,表示学生尚未注册任何课程),并初始化其他字段。`getNumClasses()`方法返回学生注册的课程数,`verifyRegistration()`方法检查学生的注册是否有效,并返回相应的布尔值。...
标题“javase子类父类继承关系图解”指的是对这一概念的可视化展示,帮助初学者更好地理解Java中的继承机制。 Java成员初始化顺序对于理解和正确使用继承至关重要。当创建一个子类对象时,其内存加载顺序遵循以下...
- **显示调用**:通过初始化列表`BaseClass(param)`在子类构造函数中显式调用基类的特定构造函数。 构造原则: - 若子类没有定义构造函数,将调用父类的无参数构造函数。 - 子类定义了构造函数时,会先执行父类...
子类可以通过`super`关键字调用父类的构造函数,确保初始化时父类的属性得到正确的设置。 总结一下,子类调用抽象父类涉及到以下主要知识点: 1. **抽象类**:不能被实例化,含有抽象方法。 2. **抽象方法**:只有...
3. 然后,创建子类实例,首先执行父类的非静态初始化块,打印出 "父类--变量" 和 "父类--初始化块"。 4. 继续执行子类的非静态初始化块,打印出 "子类--变量" 和 "子类--初始化块"。 5. 最后,执行子类的构造器,...