package one;
public class A {
protected int first;
protected static int second;
}
package two;
import one.A;
public class B extends A {
public void someMethod() {
this.first = 5; //works as expected
B.second = 6; //works
A a = new A();
// a.first = 7; does not compile
//works just fine, but why?
a.second = 8;
A.second = 9;
}
}
为什么静态字段没有相同的限制,背后的理念是什么?
答案 0 :(得分:6)
来自JLS 6.6.2:
对象的受保护成员或构造函数可以从包之外访问,其中只有负责执行的代码才能声明 那个对象。
来自6.6.2.1:
设C是声明受保护成员的类。只允许在C的子类S的主体内访问。
this.first = 5;
有效,因为B
是A
的实施者。
A.second
有效,因为此限制仅针对对象的成员定义。同样适用于B.second
。
至于为什么以这种方式指定,你必须要求定义规范的人 - 我们只能做出假设。 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;
}
}
此处的方法增量发生编译时错误:它无法访问其参数p的受保护成员x和y,因为而Point3d(对x和y字段的引用出现的类)是Point的子类(声明x和y的类),它不参与Point的实现(参数p的类型)。方法delta3d可以访问其参数q的受保护成员,因为Point3d类是Point的子类,并且参与Point3d的实现。
我建议您查看Why we should not use protected static
in Java。
protected
的语义针对的是实例成员 - protected static
与protected
的目的相矛盾,这可能就是为什么它不以同样的方式受到限制。