如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?

Posted

技术标签:

【中文标题】如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?【英文标题】:How can ‘protected static’ variable of superclass be accessed in the subclass, where subclass resides in different package..? 【发布时间】:2013-06-20 11:50:45 【问题描述】:

这是同一个问题的稍微详细的版本。

我们无法访问子类中的(超类的)受保护变量,子类在不同的包中。我们只能访问超类的继承变量。但是,如果我们将修饰符更改为“受保护的静态”,那么我们也可以访问超类的变量。为什么会这样?

这是我试图解释的相同的代码 sn-p。

package firstOne;

public class First 
    **protected** int a=7;


package secondOne;

import firstOne.*;

public class Second extends First 
    protected int a=10; // Here i am overriding the protected instance variable

    public static void main (String [] args)
        Second SecondObj = new Second();
        SecondObj.testit();
    
    public void testit()
        System.out.println("value of A in Second class is " + a);
        First b = new First();
        System.out.println("value in the First class" + b.a ); // Here compiler throws an error.
    

上述行为是预期的。但我的问题是,如果我们将超类实例变量“a”的访问修饰符更改为“受保护的静态”,那么我们也可以访问该变量(超类的变量)......!我的意思是,

package firstOne;

public class First 
    **protected static** int a=7;


package secondOne;

import firstOne.*;

public class Second extends First 
    protected int a=10;

    public static void main (String [] args)
        System.out.println("value in the super class" + First.a ); //Here the protected variable of the super class can be accessed..! My question is how and why..?
        Second secondObj = new Second();
        secondObj.testit();
    

    public void testit()
        System.out.println("value of a in Second class is " + a);
    


上面的代码显示了输出:

超类 7 中的值

test1 类中 x 的值为 10

这怎么可能……?

【问题讨论】:

我对为什么第一种情况不起作用感到更加困惑。根据the documentation on access control,我认为a 在这两种情况下都应该可见。 实例成员上的protected不是只适用于this吗?即如果你想从子类访问它,你必须使用this;它不适用于任意实例。 @Thihara:我测试了他的代码(减去额外的**s),我也得到了一个编译器错误:error: a has protected access in First @Prasad:呃,你没看懂我说的,我给你解释了!当您说protected static 时,这意味着this.a 访问与b.a 相同的变量,因此编译器允许第一个但阻止其他变量是没有意义的。当您只说protected 时,this.ab.a 不同,因此编译器允许您访问this.a,但阻止您访问b.a @Prasad:呃,你的代码和我解释的不一样。你有一个额外的protected int a=10;,它覆盖了First 中的protected static a。那只会让你更加困惑。删除它,以便您了解为什么编译器会按照我告诉您的方式运行。然后在有意义后随意将其放回原处。 【参考方案1】:

来自“检查对 Java 虚拟机中受保护成员的访问”:

m 成为在属于包 p 的类 c 中声明的成员。如果 m 是公共的,它可以被任何类(代码中)访问。如果 m 是私有的,则只能由 c 访问。如果 m 具有默认访问权限,则它只能被属于 p 的任何类访问。

如果 m 受到保护,事情会稍微复杂一些。首先,可以访问m 由属于 p 的任何类,就好像它具有默认访问权限一样。此外,它可以被 c 的任何子类 s 访问,该子类属于与 p 不同的包,但有以下限制:如果 m 不是静态的,那么其成员被访问的对象的类 o 必须是 ss 的子类em>,写成os(如果m是静态的,限制不适用:m可以总是被 s 访问)。

我在JLS, section 6.6.2.1 中找到了该引用,它支持关于“正在访问其成员的对象必须是s 或子类...”的部分。我没有看到任何支持静态子句的东西,但是根据您自己的示例,这显然是正确的。

【讨论】:

所以你的意思是说,当静态关键字与受保护的变量一起使用时,这就是行为改变的方式,并且oracle doc没有给出逻辑推理,我们只需要记住它...? 你是对的,规范中没有关于此的内容,在受保护的部分或静态部分中。或者至少据我所知。所以我认为这是规范中的一个灰色区域......【参考方案2】:

覆盖仅适用于方法,不适用于类变量。没有覆盖变量的事情。您正在隐藏访问超类的变量 a 的符号。

【讨论】:

以上是关于如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?的主要内容,如果未能解决你的问题,请参考以下文章

如何使子类只能从实例访问?

如何在 C++ 子类的构造函数中初始化超类的 const 成员变量?

QThread:如何使用受保护的静态函数

子类会在后台包含来自超类的私有方法和成员变量吗? [复制]

受保护的静态成员变量

受保护的静态方法访问