java继承机制中父类的私有成员在子类中的存在形式

一直有一个困惑,继承机制中,子类会继承父类中的所有的成员,那么子类继承父类中的这些成员后,是如何存储它们的呢?是在一个与子类不同的堆地址空间存储?还是父类中的这些成员与子类中特有的成员存储在同一个地址空间呢?下面通过以下测试代码,我们可以获得答案:

除了私有成员,这句话到底怎么理解呢?我们一起来看看下面的代码吧。

//定义了一个父类Father

class Father { 
    private String name;
    public Father(String name){
        this.name = name;
        System.out.println("father address:"+this.hashCode());
    }
}//编写son子类

public class son extends Father{
    private String name;
    public son(String name){
        super(name);
        this.name = name;
        System.out.println(this.hashCode() == super.hashCode());
    }
    
    public static void main(String[] args) {
        Father son = new son("son");
        System.out.println("son address:"+son.hashCode());
    }
}
 

测试结果如下:

father address:366712642
true
son address:366712642

程序分析:

上述测试代码中,在main方法中当创建一个子类对象son的语句 Father son = new son("son");被执行时,内存中会完成以下工作:

1:先将硬盘上指定位置的son.class文件加载进内存。

2:执行main方法时,在栈内存(栈内存中存储的是方法的局部变量)中开辟了main方法的空间(压栈-进栈),然后在main方法的栈区分配了一个变量son。

3:当执行到new语句时,JVM会在堆内存中开辟一个实体空间,分配了一个内存首地址值。

4:在该实体空间中进行属性的空间分配,并进行了默认初始化。

5:对空间中的属性进行显示初始化(对属性按照默认初始值进行初始化)。

6:进行实体的构造代码块初始化。

7:调用该实体对应的构造函数,进行构造函数初始化。(此时才是调用构造函数,执行构造函数内的初始化语句)

8:将首地址赋值给son ,son变量就引用了该实体。(指向了该对象)

在该例子中的语句 Father son = new son("son"),按照上述步骤当程序执行到第七步,栈中的名为son的引用变量指向了存储son对象的堆地址空间,同时调用son对象的构造函数,执行构造函数内的第一条语句super(name)时,会相应调用父类中的构造函数,执行父类中的构造函数内的语句,输出父类对象的内存存储的HashCode。注意在父类的构造方法被调用时并没有在堆空间重新分配一个地址空间来存储父类对象的属性,而是将父类对象构造方法中的变量的值直接存储在栈中son变量指向的内存空间中。当super(name)语句(即父类中带有一个String类型参数的构造方法)执行完毕,JVM继续执行 this.name = name; System.out.println(this.hashCode() == super.hashCode());输出结果显示this代表的本类类型的对象引用的哈希地址和子类所属父类中的内存空间引用的hash地址是相等的。代表子类和父类在同一个堆的内存空间中,该内存空间既包含了子类的所有成员,也包含了父类的所有成员(包括私有的成员都存储在此空间,只是这些父类的私有成员对子类对象是不可见的)。对此,我们也能解释清楚为什么两个不同对象的hashCode可以相等。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
子类无法直接访问父类私有成员,因为私有成员只能在定义它们的类内部访问。但是可以通过使用继承和访问控制饰符来间接地访问父私有成员。 一种常见的方式是通过在父类提供公有的getter和方法来访问私有成员。子可以通过调用这些公有方法来获取或修改父类私有成员。 另一种方式是使用protected访问控制修饰符。成员可以在子类直接访问,包括父类私有成员子类可以通过继承父类并在子类访问父类的protected成员来间接地访问父类私有成员。 下面是一个示例代码,演示了如何通过公有方法和protected访问控制修饰符来访问父类私有成员: ```java class Parent { private int privateField; public int getPrivateField() { return privateField; } public void setPrivateField(int value) { privateField = value; } } class Child extends Parent { public void accessPrivateField() { int value = getPrivateField(); System.out.println("Accessing private field in parent class: " + value); } } public class Main { public static void main(String[] args) { Child child = new Child(); child.setPrivateField(10); child.accessPrivateField(); } } ``` 在上面的示例,Parent类有一个私有成员privateField,并提供了公有的getter和setter方法来访问该私有成员。Child类继承了Parent类,并在accessPrivateField方法通过调用getPrivateField方法来访问父类私有成员privateField。 请注意,这里的示例代码仅用于演示目的,实际应用应根据具体情况来确定是否需要访问父类私有成员。在面向对象设计,尽量遵循封装原则,私有成员应该只在定义它们的类内部使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值