一个受保护的变量可以访问,而另一个则不能访问。为什么?

时间:2019-03-16 23:41:17

标签: java inheritance protected

这是一个受保护的继承问题。我确实了解到,protected意味着在软件包中,就好像它是公共的。通常,在包外部,只有在子类内部时才可以访问它。那不是我的困惑。我的困惑是正在发生一些小问题,我不知道为什么。在代码之后,我将解释问题的实质。为您提供了包含TestA类的包com.wobble.foo和包含扩展classA的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
    }
}

超类有两个受保护的变量,一个是静态的。不同包中的子类创建了一个新的超类对象,试图访问这两个变量。为什么通过对象可以通过它访问静态变量,而不能通过它访问实例变量呢?它们都受到保护。两者来自同一班级。两者都由同一个对象访问。请注意,对于那些认为这可能是重复的人:其他问题只是询问受保护的工作方式,而他们却没有提出具体问题,为什么只能访问这两个受保护变量中的一个。

-谢谢

PS:

这不是一个如何解决代码的问题。我知道如何使最终游戏正常运行。问题是为什么可以通过t.x;而不是t.y;来访问它?

1 个答案:

答案 0 :(得分:2)

 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上实例上的受保护字段。 It needs to be an instance of TestB。不过,相同的代码也可以在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
}

  

好吧,但是那我怎样才能访问t.x?它也是受保护的成员,我仍然不是。

这里完全不使用实例t(它could even be null仍然可以使用)。静态方法仅在变量的编译时(声明的)类型上分派。理想情况下,t.x should not even be allowed,但至少会收到编译器警告。


  

它是静态的,因此从技术上讲,您不是通过父类来访问它,而是通过子类来访问它?即t.x-> x-> TestB.x是通过TestB获取的?

静态方法不能被子类覆盖。 TestB.x只是一种写TestA.x的令人困惑(或方便,取决于您的外观)的方式。您可以将其视为自动从父类导入所有(公共和受保护)静态字段和变量的子类。可以减少击键次数,但不会改变行为(某些方法与实例方法的工作方式非常不同,后者是根据实际实例类型动态分配的)。

无论哪种方式,由于TestA.x受保护,因此TestA的子类(包括TestB)中的静态代码块可以访问它。