为什么Java规则适用于受保护的访问,例如它们?

时间:2017-10-20 12:18:38

标签: java

请考虑以下代码:

public class Sup {
    protected void method(){}
}

//another package
class Sub extends Sup {
    public static void main(String[] args) {
        new Sub().method();
        new Sup().method(); // does not compile
    }
}

我的问题是:为什么第二次调用不能编译?

2 个答案:

答案 0 :(得分:2)

JLS所说的

JLS的相关部分说明如下:

  

设C是声明受保护成员的类。只允许在C的子类S的主体内访问。

     

此外,如果Id表示实例字段或实例方法,则:

     
      
  • 如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则当且仅当表达式Q的类型为S或S的子类时才允许访问。

  •   
  • 如果访问是通过字段访问表达式E.Id,其中E是主表达式,或者是通过方法调用表达式E.Id(...),其中E是主表达式,那么当且仅当E的类型是S或S的子类时才允许访问。

  •   

Source

对Sup方法的调用没有通过第二条规则,因为它是一个超类,而不是一个子类。

对Sub的调用是同一个类,因此它会传递规则。

为什么会这样说

受保护的成员应该在子类的内部代码中使用,因此能够从不同的对象子类访问它将允许您影响您不应该的对象的状态。

答案 1 :(得分:1)

protected主要用于类中的实用程序帮助程序方法。它们不能从外部访问,例如private方法。

但是,扩展类可能需要访问这些方法,甚至修改它们。所以基本上它是喜欢 private,它的存在权应该是明确的,但你想给扩展类提供访问它的机会。

这种情况经常发生,他们决定在语言中加入protected。如果您有其他愿望或设计建议,请随时分享。

以下是经常引用的overview table

            | Class | Package | Subclass | Subclass | World
            |       |         |(same pkg)|(diff pkg)| 
————————————+———————+—————————+——————————+——————————+————————
public      |   +   |    +    |    +     |     +    |   +     
————————————+———————+—————————+——————————+——————————+————————
protected   |   +   |    +    |    +     |     +    |         
————————————+———————+—————————+——————————+——————————+————————
no modifier |   +   |    +    |    +     |          |    
————————————+———————+—————————+——————————+——————————+————————
private     |   +   |         |          |          |    

+ : accessible
blank : not accessible

考虑一个示例,其中提供了一些abstract基类,如AbstractMap。它可以有一种方法来重新安排内部事物。

您可以创建方法private,但也可以将其设为protected,因为扩展类可以通过覆盖来更改重新排列过程。如果扩展类由于其特定的结构而具有可用于创建方法的更有效版本的附加知识,则这可能是有用的。