Java基础:成员变量的继承与覆盖

1.前言

最近在研究Java多态时,发现子类通过继承父类来实现Java中的多态。子类可以继承父类的成员方法和成员变量。子类中如果有同名的成员方法,并且方法的参数和返回值一样,那么这个子类定义的这个方法将覆盖父类的方法。那么如果子类有同名的成员变量呢,情况又会怎么样呢?通过继承可以得到父类的成员变量,子类的成员变量包括从父类继承的成员变量(包括从祖先类中继承的成员变量)以及子类中重新定义的成员变量。本次介绍内容包括:可以继承哪些成员?如果子类和父类出现了相同的成员变量如何处理?

2.可以继承的成员变量

可以继承的成员变量与成员变量的访问控制类型有关,成员变量的访问控制类型包括public、protected、缺省的和private。

子类继承父类之后,可以继承父类的public和protected类型的成员变量。例如:

public class Parent{

      public int i_public;

      int i_default;

      protected int i_protected;

      private int i_private;

}

public class Child extends Parent{

      private int i_child;

}

父类的成员变量包括:

  • public int i_public;
  • int i_default;
  • protected int i_protected;
  • private int i_private;

子类的成员变量包括:

  • public int i_public; // 继承自父类
  • protected int i_protected;// 继承自父类
  • private int i_child; //在子类中声明的

3.覆盖父类的成员变量

假设父类中定义了成员变量i并且能够被子类继承,子类中又定义了成员变量i,这样子类中会有两个名字为a的成员变量,如何访问呢?

我们来看下面这个例子:

class Father {
    int i = 10;

    public void setI(int i) {
        this.i = i;
    }
}

class Son extends Father {
    int i = 20;

    public void show() {
        System.out.println("super.i : " + super.i + ";this.i : " + this.i);
    }
}

public class Main {
    public static void main(String[] args) {
        Son son = new Son();
        Father parent = new Son();

        System.out.println(parent.i);
        System.out.println(son.i);
        System.out.println();
        
        son.setI(100);
        son.show();
        System.out.println(son.i);
    }
}

运行结果:
10
20

super.i : 100;this.i : 20
20

首先我们要注意的是:

  1. 从父类继承的成员变量,其访问控制符仍然相同。
  2. 子类定义与父类同名的成员变量,并没有覆盖父类的成员变量,而是两个成员变量共存

即使子类声明了与父类完全一样的成员变量,也不会覆盖掉父类的成员变量。而是在子类实例化时,会同时定义两个成员变量,子类也可以同时访问到这两个成员变量(this.i&super.i),但父类不能访问到子类的成员变量(父类不知道子类的存在)。

而具体在方法中使用成员变量时,究竟使用的是父类还是子类的成员变量,则由方法所在的类决定;即,方法在父类中定义和执行,则访问的是父类的成员变量,方法在子类中定义(包括覆盖父类方法)和执行,则访问的是子类的成员变量。在方法调用中,我们通过java虚拟机JVM的内存模型来分析这个问题,在方法调用中,方法首先通过栈帧压入到虚拟机栈中。然后栈帧中的局部变量表的第一个Slot的值将传入当前对象的引用,如果是父类方法,当前对象的引用传入Father this。如果是子类方法,当前方法的引用传入Son this,如下面所示。

  • 对于 setI 方法,它的原型应该是setI(Father this, int i)
  • 而对于show方法,它的原型应该是show(Son this)

Father parent = new Son();

当存在一个子类对象向上转型为父类引用时候,对parent这个引用的访问成员变量时。访问的是父类成员变量

如何手动的选择对父类成员变量的访问还是对子类成员变量的访问?下面我们来看以下两个例子:

  1. 如果在child类中如何访问自己的成员和父类的成员内,通过super来访问,例如下面的代码:
public int getParentA(){
    return super.a;
}

public int getChildA(){
    return a;
}
  1. 访问子类的成员变量可以使用this,例如下面的代码:
public int getChildA(){
    return this.a;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值