2017-10-20 106 views
-1

考虑下面的代码:为什么受保护访问的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 
    } 
} 

我的问题是:为什么它这样的方式设计的第二个呼叫无法编译?

+0

什么是错误信息? –

+0

为什么你认为它*应该*编译? –

+0

OP不认为它应该编译。他也没有要求程序不编译的原因。 OP想知道Java中这种设计选择的原因。 – Zabuza

回答

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,因为扩展类可以通过覆盖来更改重新排列过程。如果扩展类由于其特定的结构,可以使用额外的知识来创建更高效​​的方法,这可能会很有用。

2

的JLS说什么

的JLS的相关部分表示如下:

令C是其中一个受保护的成员被声明的类。访问只内C.

另外的一个子类S的体允许的,并且,当ID表示一个实例字段或实例方法,则:

  • 如果接入是由合格的名称Q. Id,其中Q是表达式名称,则当且仅当表达式Q的类型是S或S的子类时允许访问。

  • 如果访问是通过字段访问表达式E.Id进行的,其中E是主表达式,或者通过方法调用表达式E.Id(...)(其中E是主表达式),则只有当ty E的pe是S或S的一个子类。

Source

向供应它的方法中的呼叫没有通过第二个规则,因为它是一个超类,而不是一个子类。

对Sub的调用是相同的类,所以它通过了规则。

为什么说这

protected成员打算从子类的内部代码中使用,所以能够从不同的对象的子类访问它将使你影响对象的状态,你不应该能够。