java里类的继承机制-成员变量(转)

本文通过一个具体的Java继承案例,详细解析了子类如何继承父类的成员变量与方法,特别是当子类与父类存在同名成员变量时,子类成员变量如何屏蔽父类成员变量的现象。
在网上看见一个关于java继承的问题,觉得这是很多初学java应该注意的问题。
Java代码
public abstract class A {
int i=1;
public void printI() {
System.out.println("i="+i);
}
}

public class B extneds A{
int i=2;
public static void main(String[] args) {
B b=new B();
b.printI();
}
}



那么,控制台打出来的i的值是多少?
呵呵,如果一下功夫就能说出正确结果1,那么,下面部分就不需要往下看了。

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

2、答案是2者如是说
子类B中的变量i和父类A中的变量i重名, 那么子类B中的变量i将会覆盖掉父类中的同名变量i. 则访问父类中的变量时jvm会把子类cast到父类.所以,打印出的结果应该是“i=2”;

3、歧义的产生
歧义的产生最关键的地方是子类B中的变量i将会覆盖掉父类中的同名变量i的覆盖两个字。这里,我觉得这两个字容易误导。应该改为屏蔽或隐藏。因为在这里父类的成员变量是没有被改变。

4、jvm的执行过程
(1)子类B 的构造方法被调用,实例化一个B对象,B对象的成员被初始化
(2)jvm隐含的调用父类的构造方法,实例化一个A对象,A对象的成员被初始化。
(3)由于A对象的printI()未被屏蔽,所以调用的A对象的printI()函数。
那么,在这里A的成员函数当然是访问自己的成员变量了。

5、super关键字
super关键字在java中的作用是使被屏蔽的成员变量或者成员方法或变为可见,或者说用来引用被屏蔽的成员变量和成员成员方法。super是用在子类中,目的是访问直接父类中被屏蔽的成员。上面的代码也可以这样写:
Java代码

  public abstract class A {
int i=1;
public void printI() {
System.out.println("i="+i);
}
}
public class B extends A{
public int i=2;
public void printI(){
super.printI();
}
public static void main(String[] args){
B b= new B();
b.printI();

}
}
### Java 中子继承成员变量机制Java 的面向对象编程中,子会自动继承中的成员变量和方法。然而,这种继承行为受到访问控制符的影响。以下是关于子如何继承成员变量的具体机制: #### 1. **成员变量继承** 子能够继承中声明为 `protected` 或者 `public` 的成员变量[^1]。如果父成员变量被声明为 `private`,则该变量不会被子直接继承,尽管如此,在创建子实例时,父的私有成员仍然会在内存中存在并初始化其默认值或指定值。 对于没有显式访问修饰符(即默认包级私有)的情况,只有当子与父位于同一个包内时才能访问这些成员;否则它们对子而言是不可见的[^2]。 #### 2. **成员变量的隐藏** 当子定义了一个与其父相同名称的成员变量时,会发生成员变量的隐藏现象。这意味着子中的同名成员变量覆盖了来自父的那个版本。在这种情况下,通过子对象操作这个共享名字的变量,默认只会引用到子自己定义的那一份副本。要明确地访问父中的那个原始成员,则需借助于 `super` 关键字来完成[^5]。 例如: ```java class Parent { public String name = "Parent"; } class Child extends Parent { public String name = "Child"; void displayNames() { System.out.println(super.name); // 输出: Parent System.out.println(this.name); // 输出: Child } } ``` 在此例子中展示了即使两者都有名为 `name` 的属性,但由于上下文的不同而分别指向各自的域。 #### 3. **静态 vs 实例成员变量** 需要注意的是,无论是静态还是非静态(实例),只要满足可访问条件都会被考虑进入继承范围之内。不过有一点区别在于,如果是静态成员的话,即便是在不同之间也只有一份单独的存在形式,并且总是优先关联至最初声明它的那个别之上而不是具体的某个派生实体上去查找匹配项[^4]。 总结来说,Java 提供了一套清晰明了却又灵活多变的方式来处理基底型及其衍生出来的各种特性之间的关系——特别是围绕着数据存储单元方面所做的安排更是体现了这一点的重要性所在!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值