如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?
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.a
与b.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 必须是 s 或 s 的子类em>,写成o≤s(如果m是静态的,限制不适用:m可以总是被 s 访问)。
我在JLS, section 6.6.2.1 中找到了该引用,它支持关于“正在访问其成员的对象必须是s 或子类...”的部分。我没有看到任何支持静态子句的东西,但是根据您自己的示例,这显然是正确的。
【讨论】:
所以你的意思是说,当静态关键字与受保护的变量一起使用时,这就是行为改变的方式,并且oracle doc没有给出逻辑推理,我们只需要记住它...? 你是对的,规范中没有关于此的内容,在受保护的部分或静态部分中。或者至少据我所知。所以我认为这是规范中的一个灰色区域......【参考方案2】:覆盖仅适用于方法,不适用于类变量。没有覆盖变量的事情。您正在隐藏访问超类的变量 a 的符号。
【讨论】:
以上是关于如何在子类中访问超类的“受保护的静态”变量,子类位于不同的包中......?的主要内容,如果未能解决你的问题,请参考以下文章