JAVA 继承 父类子类 内存分配

本文深入探讨Java中继承的概念,包括多继承限制、成员变量与方法的继承规则,通过程序示例展示如何加载类、分配内存空间及方法执行过程。解释了私有成员变量的继承、被屏蔽成员的含义及作用,最终解答疑惑并总结继承机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


继承的基本概念:
(1)Java不支持多继承,也就是说子类至多只能有一个父类。
(2)子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法。
(3)子类中定义的成员变量和父类中定义的成员变量相同时,则父类中的成员变量不能被继承。
(4)子类中定义的成员方法,并且这个方法的名字返回类型,以及参数个数和类型与父类的某个成员方法完全相同,则父类的成员方法不能被继承。

分析以上程序示例,主要疑惑点是“子类继承父类的成员变量,父类对象是否会实例化?私有成员变量是否会被继承?被继承的成员变量在哪里分配空间?”
1:虚拟机加载ExtendsDemo类,提取类型信息到方法区。
2:通过保存在方法区的字节码,虚拟机开始执行main方法,main方法入栈。
3:执行main方法的第一条指令,new Student(); 这句话就是给Student实例对象分配堆空间。因为Student继承Person父类,所以,虚拟机首先加载Person类到方法区,并在堆中为父类成员变量在子类空间中初始化。然后加载Student类到方法区,为Student类的成员变量分配空间并初始化默认值。将Student类的实例对象地址赋值给引用变量s。
4:接下来两条语句为成员变量赋值,由于name跟age是从父类继承而来,会被保存在子类父对象中(见图中堆中在子类实例对象中为父类成员变量分配了空间并保存了父类的引用,并没有实例化父类。),所以就根据引用变量s持有的引用找到堆中的对象(子类对象),然后给name跟age赋值。
4:调用say()方法,通过引用变量s持有的引用找到堆中的实例对象,通过实例对象持有的本类在方法区的引用,找到本类的类型信息,定位到say()方法。say()方法入栈。开始执行say()方法中的字节码。
5:say()方法执行完毕,say方法出栈,程序回到main方法,main方法执行完毕出栈,主线程消亡,虚拟机实例消亡,程序结束。

总结:相同的方法会被重写,变量没有重写之说,如果子类声明了跟父类一样的变量,那意味着子类将有两个相同名称的变量。一个存放在子类实例对象中,一个存放在父类子对象中。父类的private变量,也会被继承并且初始化在子类父对象中,只不过对外不可见。

super关键字在java中的作用是使被屏蔽的成员变量或者成员方法变为可见,或者说用来引用被屏蔽的成员变量或成员方法,super只是记录在对象内部的父类特征(属性和方法)的一个引用。啥叫被屏蔽的成员变量或成员方法?就是被子类重写了的方法和定义了跟父类相同的成员变量,由于不能被继承,所以就称作被屏蔽。
说到这里,上面提出的疑惑也就解开了。


原创文章,转载请注明出处: http://blog.youkuaiyun.com/thinking_in_android
### Java 父类 子类 继承 示例 代码 教程 #### 定义父类子类Java中,定义一个简单的父类`ParentClass`,该类有一个方法用于打印消息: ```java class ParentClass { public void printMessage() { System.out.println("这是父类的方法"); } } ``` 接着创建一个继承自`ParentClass`的子类`ChildClass`,并重写父类中的`printMessage()`方法来展示不同的行为[^3]。 ```java class ChildClass extends ParentClass { @Override public void printMessage() { System.out.println("这是子类重写的方法"); } } ``` 为了测试这两个类的行为,在主函数中实例化子类对象,并调用其方法查看输出结果: ```java public class Main { public static void main(String[] args) { ChildClass child = new ChildClass(); child.printMessage(); // 输出 "这是子类重写的方法" } } ``` 上述例子展示了如何让子类覆盖来自父类的方法实现。这有助于提高代码灵活性以及适应特定需求下的功能调整。 #### 构造器链式调用 除了属性方法外,构造器也可以被子类所利用。考虑另一个场景,如果希望初始化过程中传递参数给父类,则可以在子类构造器内部使用关键字`super()`显式地调用父类带参构造器[^4]。 ```java class Parent { private int value; public Parent(int value) { this.value = value; } } class Child extends Parent { private String name; public Child(int value, String name) { super(value); this.name = name; } } ``` 在这个案例里,每当创建一个新的`Child`对象时都会先执行一次`Parent`类里的构造逻辑,从而确保了数据成员能够得到恰当设置。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值