简体   繁体   English

Java:对超类对象上的子类的受保护访问限制

[英]Java : Protected access restriction for subclass on superclass object

I know that this has been asked before in this forum but i will ask again since i don't see any good answer (so far).我知道之前在这个论坛上有人问过这个问题,但我会再问一次,因为我没有看到任何好的答案(到目前为止)。

Here it goes:它是这样的:

package a;
public class A{
    protected int a;
}

package b;
public class B extends A{
}

package c;
public class C extends B{
    public void accessField(){
        A ancient = new A();
        ancient.a = 2;  //A - That wouldn't work.

        a = 2;   //B - That works.
    }

}

Why clause A) won't work?为什么 A) 条款不起作用? What's the rational behind this restriction on superclass object ancient access in subclass C?子类 C 中对超类对象古代访问的这种限制背后的原因是什么?
Thanks.谢谢。

Protected members can only be accessed outside of the same package if it's via inheritance - ie within the hierarchy.受保护的成员只能在同一个包之外通过继承访问——即在层次结构内。

So when you're creating another instance of A from a different package, that's not an inheritance relationship and it thus fails.因此,当您从不同的包创建 A 的另一个实例时,这不是继承关系,因此会失败。

As always, this is covered in the JLS, 6.6.2:与往常一样,这在 JLS 6.6.2 中有介绍:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.对象的受保护成员或构造函数可以从包外部访问,在该包中仅由负责实现该对象的代码声明它。

Actually you don't need two levels of inheritance and the code below would lead to the same behaviour:实际上,您不需要两级继承,下面的代码会导致相同的行为:

public class B extends A{
     public void accessField() {
        A ancient = new A();
        ancient.a = 2;  //A - That wouldn't work.

        a = 2;   //B - That works.
    }
}

The reason why a = 2 works is JLS 6.2.2.1 : a = 2工作的原因是JLS 6.2.2.1

Let C be the class in which a protected member is declared.设 C 是声明受保护成员的类。 Access is permitted only within the body of a subclass S of C.只允许在 C 的子类 S 的主体内访问。

Note that it does not say direct subclass, but only subclass.请注意,它没有说直接子类,而只是说子类。 So a = 2 works within the B class or the C class.所以a = 2B类或C类中工作。

On the other hand, ancient.a = 2;另一方面, ancient.a = 2; is covered by the next bullet point in the same section:包含在同一部分的下一个要点中:

If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S.如果访问是通过限定名称 Q.Id 进行的,其中 Q 是 ExpressionName,那么当且仅当表达式 Q 的类型是 S 或 S 的子类时才允许访问。

In your case, Q.Id is ancient.a => it would only be accessible if the type of ancient was B or a subclass of B .在你的情况, Q.Idancient.a =>那只如果访问的类型ancientB或子类B So for example, this would compile:例如,这将编译:

public class B extends A{
     public void accessField() {
        C ancient = new C();
        ancient.a = 2;  //A - That wouldn't work.
     }
}

Quoting from book The Java Programming Language 3 ed.引自 The Java Programming Language 3 ed 一书。 by Gosling et all - page 81 sec 3.5作者:Gosling 等人 - 第 81 页 3.5

"What Protected really means" - .. beyond being accessible within the class itself and to code within the same package , a protected member can also be accessed from a class through object references that are of atleast the same type as the class - that is references of class's type or one of its subclass “受保护的真正含义” - .. 除了可以在类本身中访问以及在同一个包中进行编码之外,还可以通过与类至少具有相同类型的对象引用从类访问受保护成员 - 即类的类型或其子类之一的引用

Quoting from JLS 6.6.2引用JLS 6.6.2

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.对象的受保护成员或构造函数可以从包外部访问,在该包中仅由负责实现该对象的代码声明它。

When you say,当你说,

A ancient = new A();
ancient.a = 2;

you are not inheriting anything from ancient (A object) and thus not responsible for its implementation.您没有从古代(一个对象)继承任何东西,因此不对其实现负责。 By making C extends A , you have already inherited 'a' from a different A object, hence the statement below works.通过使C 扩展 A ,您已经从不同的 A 对象继承了 'a',因此下面的语句有效。

a = 2;

If,如果,

ancient.a = 2;

works, then there is not difference between a public and a private access specifier.有效,那么公共和私有访问说明符之间没有区别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM