以下是代码:
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在不同的包中访问...
答案 0 :(得分:4)
由于可以从任何包中的子类访问protected
成员这一事实已广为人知,因此我回答了问题的另一面:为什么protected
实例字段不对子类可见?
与往常一样,寻找权威答案的地方是Java语言规范,在本例中为Section 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
发生编译时错误:它无法访问其参数x
的受保护成员y
和p
,因为{{1} (Point3d
和x
字段的引用所在的类)是y
的子类(Point
和x
所在的类声明),它不参与y
(参数类型Point
)的实现。方法p
可以访问其参数delta3d
的受保护成员,因为类q
是Point3d
的子类,并且参与Point
的实现}。方法delta可以尝试将其参数(§5.5,§15.16)转换为
Point3d
,但是如果运行时的p类不是{{{},则此转换将失败,从而导致异常。 1}}。方法
Point3d
中也发生编译时错误:它无法访问其参数Point3d
的受保护成员warp
,因为虽然类z
(在a
(参数类型Point
)的实现中涉及对z
字段Point3d
的引用“的类所涉及的类,它不是a
的子类(声明Point3d
的类。)
答案 1 :(得分:2)
受保护意味着所有子类都可以访问它,以及同一个包中的所有其他类。在这种情况下,C
是A
的子类,因此无论其所在的包是什么,都可以访问这些字段。
子类C
无法访问任何其他A
对象的受保护字段,但只能访问C
个对象。因此,它可以访问this.var2
,如果您将A test;
更改为C test;
(并初始化为test = new C();
,则可以访问它。