1 回答

TA贡献1847条经验 获得超7个赞
t.x = 1; //compiles
这是一个字段。所以你应该把它写成(会有一个编译器警告)。staticTestA.x
静态受保护字段可从子类的静态代码(或从非静态代码中)访问。
t.y = 2; //field not visible, fails to compile
这是一个实例字段。可以从子类上的实例方法中访问受保护的实例字段。但只能从这些方法中。不能从静态方法调用它们(即使该静态方法恰好位于子类上)。
如果需要从另一个类中的静态方法访问字段,则需要公开该字段或将需要它的代码移动到同一包中。
但只能从这些方法中。
而且,只有当您可以确定所讨论的实例实际上来自您自己的类时。
在您的示例中
TestA t = new TestA();
t.y = 2;
t.y不可见,因为 中的代码无法访问 中的实例上的受保护字段。它需要是 TestB 的一个实例。不过,相同的代码可以在 上的方法中工作。TestBTestATestA
以下方法也不起作用:
// in TestB
void boo(TestA someInstance){
this.y = someInstance.y;
// does not compile, because someInstance.y is not visible
// because it could be from unknown TestC
}
好吧,这是有道理的,但是我该如何访问t.x?它也是一个受保护的成员,我仍然不是t。
此处根本不使用该实例(它甚至可能为 null,代码仍然有效)。静态方法仅在变量的编译时(声明)类型上调度。理想情况下,甚至不应该被允许,但至少你会得到一个编译器警告。tt.x
它是静态的,所以从技术上讲,你不是通过超类访问它,而是通过子类访问它?即 t.x -> x -> TestB.x 通过 TestB 获取它?
子类不能重写静态方法。 只是一种令人困惑(或方便,取决于你如何看待它)的写作方式。您可以将其视为从父类自动导入所有(公共和受保护的)静态字段和变量的子类。使击键次数减少,但不会改变行为(当然,其工作原理与实例方法非常不同,实例方法在实际实例类型上动态调度)。TestB.xTestA.x
无论哪种方式,由于受保护,因此 可由 的子类中的静态代码块访问,包括 。TestA.xTestATestB
添加回答
举报