2015-08-29 32 views
16

在他的书中,Herbert Schildt在第172页(第3段)中说,“保护只适用于涉及继承时”。在Java中,为什么可以在同一个包中从类之外访问受保护的成员?

在页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); 
    } 
} 

它是好的,可变可以从衍生访问class Class2。但是,如何通过对Class1的对象的引用,从非派生类Class3访问它?它与第172页的声明相矛盾。如果是这样,那么在这种情况下,我发现公共和受保护说明符之间没有区别。即宣告protectedis visible to itself, its children, and the package it's declared in.

如果Class3是在不同的包,像mypack.nested

+0

Herbert Schildt的书通常不是那么好,而且充满了不准确之处。 –

回答

2

的东西,那么你将无法访问class1.pro可言。

17

在他的书中,赫伯特·希在第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 

注意没有修饰符授予既类和包访问成员,并且不授予访问子类或世界。 protected只会改变其中的一件事情:它使该成员可用于子类。所以从这个意义上说,他是正确的:它只适用于涉及继承时;没有继承,就和没有修饰符一样。

但我觉得这很容易让人误解,因为这个原因激发了你的问题:它似乎暗示不会有包访问。声明有意义的唯一方法是如果您已知道无修饰符授予包访问权限。

为清楚起见:protected表示成员可用于包中的任何类以在子类中进行编码。这样做可以让图书馆拥有只能从图书馆* (有点见下)或帮助在图书馆实现某些内容的代码的代码访问的字段和方法(例如,如果你是从一个库类继承)。没有什么特别的“为什么”,而不是这种语言的设计。

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

在这种情况下,没有。但是,当您考虑代码不是,并且不在包成员的派生类中时,显然存在相当大的区别:该代码无法访问protected成员。

这是覆盖在JLS§6.6.1

...如果成员或构造声明protected,然后访问只允许在下列条件之一为真:

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

  • 访问权限正如第6.6.2节所述。

(注意第一子弹)和JLS§6.6.2

protected构件或构造方法的对象可以从它仅由代码中声明的封装外部访问,其负责用于实现该对象。

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


*真是我“之类的,看下面的” on “这样做可以使图书馆具有您只能从库的一部分代码访问的字段和方法......”这不是真的,因为除了受限制的软件包(例如,java.lang),你可以愉快地写你自己的类,说它在库的包中,然后使用库类的包级别字段和方法。 Java的包概念不是字段/方法安全机制。

+0

OP知道'protected'的规则。问题是关于'为什么一个受保护的成员能够在整个包中可见' –

+4

@sᴜʀᴇsʜᴀᴛᴛᴀ:这就是我回答的问题:因为这就是它在规范中定义的方式,在指定的部分。 –

+0

感谢您的详细解答。 –

0

如果是这样的话,我觉得公众和 保护符之间没有差别在这种情况下

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

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 
    } 
} 

在代码在不同的包公开的情况和保护是不同的。除非派生类中这样做,否则您可以使用来自不同软件包但不受保护成员的公共成员。

相关问题