java - 一个受保护的变量是可访问的,而另一个则不是。为什么?
问题描述
这是一个受保护的继承问题。我确实理解 protected 意味着在一个包中,它就好像它是公共的。在包之外,一般来说,只有在子类内部时才能访问它。那不是我的困惑。我的困惑在于正在发生的一个小问题,我不知道为什么。我将在代码之后解释问题的核心。您将获得包含 TestA 类的包 com.wobble.foo 和包含扩展类 A 的 TestB 类的 com.wobble.bar。
//A Package
package com.wobble.foo;
public class TestA{
static protected int x = 5;
protected int y = 6;
}
//A different Package
package com.wobble.bar;
public class TestB extends TestA{
static{
TestA t = new TestA();
t.x = 1; //compiles
t.y = 2; //field not visible, fails to compile
}
}
超类有两个受保护的变量,一个是静态的。不同包中的子类创建了一个新的超类对象,试图访问这两个变量。为什么你可以通过对象通过它访问静态变量,但不能通过它访问实例变量?它们都受到保护。两人同班。两者都由同一个对象访问。请注意,对于那些认为这可能是重复的人:其他问题只是询问受保护的工作原理,但他们没有提出具体问题,即为什么只能访问这两个受保护的变量中的一个。
这不是一个如何修复代码的问题。我知道如何让最终游戏发挥作用。问题是为什么它可以通过t.x;
但不能访问t.y;
?
解决方案
t.x = 1; //compiles
这是一个static
领域。所以你应该把它写成TestA.x
(会有一个编译器警告)。
静态受保护字段可从子类的静态代码(或非静态代码)中访问。
t.y = 2; //field not visible, fails to compile
这是一个实例字段。受保护的实例字段可以从子类的实例方法中访问。但只能从这些方法中。您不能从静态方法调用它们(即使该静态方法恰好位于子类上)。
如果您需要从另一个类中的静态方法访问字段,则需要将该字段设为公共或将需要它的代码移动到同一个包中。
但只能从这些方法中。
只有当您可以确定所讨论的实例实际上来自您自己的类时。
在你的例子中
TestA t = new TestA();
t.y = 2;
t.y
不可见,因为中TestB
的代码无法访问来自TestA
. 它必须是TestB
. 不过,相同的代码可以在 on 方法中运行TestA
。
以下也不起作用:
// 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
}
好的,这是有道理的,但是我怎样才能访问 tx?它也是受保护的成员,我仍然不是。
该实例t
在这里根本没有使用(它甚至可能是null
并且代码仍然可以工作)。静态方法仅在变量的编译时(声明的)类型上调度。理想情况下,t.x
甚至不应该被允许,但至少你会收到编译器警告。
它是静态的,所以从技术上讲,您不是通过超类而是通过子类访问它?ietx -> x -> TestB.x 是通过 TestB 获得的吗?
静态方法不能被子类覆盖。TestB.x
只是一种令人困惑(或方便,取决于您如何看待它)的编写方式TestA.x
。您可以将其视为子类自动从父类导入所有(公共和受保护的)静态字段和变量。减少击键次数,但不会改变行为(肯定与实例方法有很大不同,实例方法在实际实例类型上动态分派)。
无论哪种方式,因为TestA.x
受到保护,它可以被 的子类中的静态代码块访问TestA
,包括TestB
.