这里有以下代码:
package ab:
public class A {
protected static int var = 10;
protected int var2 = 20;
}
和
package cd;
public class C extends A {
A test;
public C(){
test = new A();
}
void printValues(){
System.out.println(A.var); //this is perfectly visible
System.out.println(test.var2); // here I get error saying var2 is not visible
}
}
我不明白为什么静态保护字段可以通过不同包中的A访问。。。
由于protected
成员可以从任何包中的子类访问这一事实大家都很熟悉,所以我回答您的另一个问题:为什么protected
实例字段对子类不可见?
和往常一样,寻找权威答案的地方是Java语言规范,在本例中是第6.6.2节。我引用那里的例子是因为它比前面的法律术语更容易理解
TL;DR:最好的方法是:protected
是继承的内部类。从其所有子类的角度来看,A.var2
的行为类似于的私有成员,每个子类单独,而不是超类的成员。所有这一切都到位了,因为protected
旨在用于为扩展设计的类中,这样子类就可以访问那些被视为扩展类的公共API的部分,而不是该类的客户端。
为了完成你的一系列例子,我再提交两个:
System.out.println(this.var2); // works---intended use of protected
System.out.println(((A)this).var2); // fails same as your test.var2
思考的食物:)
示例6.6.2-1。访问受保护的字段、方法和构造函数
考虑这个例子,其中points包声明:
package points; public class Point { protected int x, y; void warp(threePoint.Point3d a) { if (a.z > 0) // compile-time error: cannot access a.z a.delta(this); } }
threePoint
包声明:package threePoint; import points.Point; public class Point3d extends Point { protected int z; public void delta(Point p) { p.x += this.x; // compile-time error: cannot access p.x p.y += this.y; // compile-time error: cannot access p.y } public void delta3d(Point3d q) { q.x += this.x; q.y += this.y; q.z += this.z; } }
方法
delta
在这里发生了编译时错误:它不能访问其参数p
的受保护成员x
和y
,因为Point3d
(对字段x
和y
进行引用的类)是Point
(声明x
和y
的类)的子类,它不涉及CCD_ 17(参数CCD_。方法delta3d
可以访问其参数q
的受保护成员,因为类Point3d
是Point
的子类并且涉及Point3d
的实现。方法delta可以尝试将其参数强制转换(§5.5,§15.16)为
Point3d
,但如果运行时p的类不是Point3d
,则此强制转换将失败,从而导致异常。方法
warp
中也会出现编译时错误:它无法访问其参数a
的受保护成员z
,因为尽管类Point
(对字段z
进行引用的类)参与了Point3d
(参数a
的类型)的实现,但它不是Point3d
(声明z
的类)的子类。
受保护意味着所有子类以及同一包中的所有其他类都可以访问它。在这种情况下,C
是A
的子类,因此可以访问字段,而不管它在哪个包中
不过,子类C
不能访问任何其他A
对象的受保护字段,只能访问C
对象。因此,它可以访问this.var2
,如果您将A test;
更改为C test;
(并将初始化更改为test = new C();
,则可以访问它。