黑马程序员技术交流社区

标题: 解释 private成员变量的继承问题 [打印本页]

作者: 赵玮_Tom    时间: 2012-5-6 11:24
标题: 解释 private成员变量的继承问题
本帖最后由 赵玮_Tom 于 2012-5-6 11:26 编辑

昨天有同学问了一个父类私有成员变量能否被子类继承的问题,觉得是一个很小却又容易被忽视的知识点,今天做一下详细解释,不正确的地方请多多指正。
原帖地址http://bbs.itheima.com/thread-13787-1-1.html
关于子类是否可以访问父类中的私有变量,以及如何访问的问题,请看如下代码:
  1. class Fu
  2. {
  3. private String name="zhangsan";// 父类私有变量
  4. public void show()
  5. {
  6. System.out.println("show run");
  7. }
  8. public String getName()//对外提供私有变量的访问方法
  9. {
  10. return this.name;
  11. }
  12. }
  13. class Zi extends Fu
  14. {
  15. public void showName()
  16. {
  17. //System.out.println(this.name);//编译报错,不能访问父类私有变量
  18. //System.out.println(super.name);//编译报错,不能访问父类私有变量
  19. //System.out.println(super.getName());//正确执行
  20. System.out.println(this.getName());//正确执行
  21. }
  22. }
  23. class ExtendsDemo
  24. {
  25. public static void main(String args [])
  26. {
  27. Zi z = new Zi();
  28. z.showName();
  29. }
  30. }
复制代码
结论:子类确实不能直接访问父类私有成员变量,但可以通过父类的getter方法间接访问父类私有成员变量。
如果在做进一步分析,其实堆内存中创建的子类对象中包含着一个父类的引用(原帖7楼附图),而私有成员变量在父类中是真实存在的,所以子类不能直接对其访问,但可以通过特定方法(如getter方法)间接访问。
我们可以形象的这样理解:父亲把自身的全部财产留给了儿子,但这些财产中也包含一些父亲年轻时的情书(私有成员变量name),这些情书被父亲锁在了一个箱子里,所以即使儿子继承了这个箱子,也无法看到情书内容。
但如果儿子无意中找到了这把箱子的钥匙(getName()方法),那儿子是可以知道情书内容的。
如果父亲早就把钥匙销毁了(也就是说父类根本就不提供getName()方法),那么儿子将不可能得到父亲情书的内容(无法访问name)。

作者: 姚鑫    时间: 2012-5-6 11:31
总结的很经典,学习了。
作者: 钟成军    时间: 2012-5-6 11:36
楼主讲得真好,例子举得很贴切,呵呵
作者: 徐慧书    时间: 2012-5-6 11:47
说的好,不过即使我们没有这个钥匙,还可以看到父亲的情书的,个人补充一些
java提供的反射技术可以达到,修改了一些代码
如下:
import java.lang.reflect.Field;

class Fu
{
private String name="zhangsan";// 父类私有变量
public void show()
{
System.out.println("show run");
}
public String getName()//对外提供私有变量的访问方法
{
return this.name;
}
}
class Zi extends Fu
{
public void showName()
{
        //System.out.println(this.name);//编译报错,不能访问父类私有变量
        //System.out.println(super.name);//编译报错,不能访问父类私有变量
        //System.out.println(super.getName());//正确执行
        System.out.println(this.getName());//正确执行
       
        //增加的代码
        try {
                Field fieldName = Fu.class.getDeclaredField("name");
                fieldName.setAccessible(true);
                String value = (String)fieldName.get(this);
                System.out.println(value);    //输出父类私有成员变量的值
        } catch (Exception e) {
                System.out.println("父类中确实不存在 name 属性");
        }
       
}
}
class Test
{
public static void main(String args [])
{
        Zi z = new Zi();
        z.showName();
}
}
技术交流




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2