首页 > 解决方案 > 一个受保护的变量是可访问的,而另一个则不是。为什么?

问题描述

这是一个受保护的继承问题。我确实理解 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;

标签: javainheritanceprotected

解决方案


 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.


推荐阅读