2016-02-11 120 views
1

我知道在Java中,只要超类提供公共或受保护的getter方法,就可以访问子类中的超类私有成员。然而我也知道这个子类实际上并没有继承私有成员。考虑以下情形....Java通过受保护的getter访问私有超类成员

Class A { 
    private var = 2; 
    protected int getVar(){ 
     return var; 
    } 
} 

Class B extends A{ 

    public void printVar(){ 
     System.out.println(getVar()); 
    } 
} 

Class Main{ 

    public static void main(args []){ 

     B b= new B(); 
     b.printVar(); 
    } 
} 

我想明白了,因为我们正在创建的子类B的一个实例,究竟当的是,私有成员分配到存储,什么是它的范围是什么?因为A的一个实例实际上从来没有创建过,它究竟是如何存在的?它不是一个静态变量,或最终它是堆栈动态还是隐式堆动态?我认为当你从一个超类实例化一个子类时,你继承了非私有成员和方法,然后那些被实例化为子类的对象实例的一部分(除非它们被覆盖等),所以只有一个对象被分配为堆动态变量。但是,如果这些私有成员没有被继承,那么编译器是否仅仅为这些私有成员提供了一个堆栈动态引用,以防在调用继承的getter方法的情况下,只有在这种情况下?

回答

2

但是我也知道子类实际上并没有继承私有成员。

是的。 B的实例是A的实例,它包含所有相同的字段。您不再可以直接访问私人领域,但他们仍然存在。

它是如何存在的,因为A实例实际上从未创建过?

当您创建B,在A一个构造函数被调用为好,这可确保B实例正确初始化为有效A。不要认为子类与超类不同。 A B仍然是A;它只是做更多。

3

你认为超类的私人成员不被子类继承是错误的。所有成员都被继承。子类的私有成员是子类实例的一部分,但不能直接由子类的代码访问。

在超级类中有一个受保护的getter,它返回私有成员的值,从而为子类提供了访问私有成员值的方法(尽管它不能修改它,除非你也有一个超级中受保护的或公共二传手)。

+0

根据JLS虽然....或我误解了这一点? (http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#8.2): 声明为private的类的成员不会被该类的子类继承。只有被声明为protected或public的类的成员才会被声明在包中声明的子类继承。 –

+0

啊,不要以为,在仔细观察它之后,我不知道它在说什么。 –

+0

@LorenShqipognja我想这是一个解释的问题。通过“不继承”,JLS意味着私人成员不能被子类访问。它们仍然由超级代码分配和初始化。 – Eran