在Java中,为什么可以在同一个包中从类外部访问受保护的成员?

时间:2015-08-29 05:52:05

标签: java protected

在他的书中,Herbert Schildt在第172页(第3段)中说,#34; 受保护仅在涉及继承时适用。"。

在第228页中,表9-1显示可以从同一个包中的非子类访问受保护的成员。

以下代码适用并支持表9-1中的信息。

Class1.java:

package Mypack;
public class Class1
{
    protected pro=1;
    public Class1()
    {
        System.out.println(pro);
    }
}

Class2.java

package Mypack;
class Class2 extends Class1
{
    Class2()
    {
        System.out.println(pro);
    }
}

Class3.java

package Mypack;
class Class3
{
    Class3()
    {
        Class1 class1=new Class1();
        System.out.println(class1.pro);
    }
}

可以从派生类 Class2 访问变量 pro 。但是如何通过引用Class1的对象从非派生类 Class3 访问它?它与第172页上的陈述相矛盾。如果是这样,那么在这种情况下我发现公众和受保护的说明者之间没有区别。

5 个答案:

答案 0 :(得分:19)

  

在他的书中,Herbert Schildt在第172页(第3段)中说“受保护仅在涉及继承时适用。”。

有一种观点认为这种说法是正确的,尽管我认为这是非常误导的。让我们看一下the access control tutorial的访问权限表:

Modifier    Class  Package  Subclass  World
public        Y       Y        Y       Y
protected     Y       Y        Y       N
no modifier   Y       Y        N       N
private       Y       N        N       N

请注意, no modifier 授予对成员的类和包访问权限,并且不授予对子类或世界的访问权限。 protected只更改其中一项:它使成员可用于子类。所以在这个意义上,他是正确的:它只适用于涉及继承的情况;没有继承,它与没有修饰符相同。

但是我觉得这很有误导性,因为这个问题启发了你的问题:似乎暗示不会有包访问。声明唯一有意义的方法是,如果您已经知道 no modifier 授予包访问权限。

为清楚起见:protected表示成员可用于包中的任何类,以便在子类中进行编码。这样做可以使库具有只能从库* (有点,见下文)的代码访问的字段和方法,或者有助于在库中实现某些内容的代码(例如,如果你从一个库类中继承子类)。除了语言的设计方式之外,没有特别的“为什么”。

  

如果是这样,那么在这种情况下,我发现公共和受保护的说明符之间没有区别。

在这种情况下,没有。但是,当您考虑在同一个包中不是并且不在包成员的派生类中的代码时,显然存在很大差异:该代码无法访问{{1成员。

这涵盖在JLS§6.6.1

  

...如果成员或构造函数声明为protected,则只有在满足下列条件之一时才允许访问:

     
      
  • 从包含声明受保护成员或构造函数的类的包中发生对成员或构造函数的访问。

  •   
  • 访问是正确的,如§6.6.2。

  • 中所述   

(请注意第一个项目符号)和JLS§6.6.2

  

对象的protected成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

(“负责实现该对象的代码” - 例如,子类中的代码。)

*我的“有点,见下文” on “这样做可以使库中的字段和方法只能从代码库中访问。 。“这不是真的,因为除了受限制的包(例如protected)之外,你可以愉快地编写自己的类,说它在库的包中,然后使用包级别字段和图书馆课程的方法。 Java的包概念不是字段/方法安全机制。

答案 1 :(得分:4)

  

protected修饰符指定只能在其自己的包中访问该成员(与package-private一样),此外,还可以在另一个包中通过其类的子类访问该成员。 https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

答案 2 :(得分:2)

声明io_service is visible to itself, its children, and the package it's declared in.

的内容

如果protected位于其他软件包中,例如Class3,则您根本无法访问mypack.nested

答案 3 :(得分:1)

此链接上的表格显示了修饰符与可以访问http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html的内容。然后根据诸如封装等良好原则需要分享的需要共享的内容等因素来选择修饰符

访问级别

Modifier Class Package Subclass World

公共Y Y Y Y

受保护Y Y Y N

无修饰符Y Y N N

私人Y N N N

答案 4 :(得分:1)

  

如果是这样,那么我发现公众和公众之间没有区别   在这种情况下受保护的说明符

这是正确的,在这种情况下没有区别 请考虑以下代码:

package otherpack;
public class Class4
{
    Class4()
    {
        Class1 class1=new Class1(); // Ok, Class1 and it's constructor are public
        System.out.println(class1.pro); // Compilation error. pro is protected
    }
}

package otherpack;
public class Class5 extends Class1
{
    Class5()
    {
        Class1 class1=new Class1(); // Ok, Class1 and it's constructor are public
        System.out.println(class1.pro); // OK, Class5 extends Class1 and pro is protected
    }
}

在不同包中的代码的情况下,public和protected是不同的。您可以使用来自不同包但不包含受保护成员的公共成员,除非您在派生类中执行此操作。