为什么一个类不能被定义为保护?

我知道这是一个愚蠢的问题,但我仍然有疑问需要清除。

我的问题是为什么我们不能将一个类定义为protected。

我知道我们不能,但为什么? 应该有一些具体的原因。

因为这是没有意义的。

受保护的类成员(方法或variables)就像包私有(默认可见性),除了它也可以从子类访问。
由于在Java中没有“子包”或“包inheritance”这样的概念,所以声明类保护或包私有将是同样的事情。

不过,可以将嵌套类和内部类声明为protected或private。

正如你所知道的默认是包级访问和保护是包级别加非包类,但它扩展了这个类(这里要注意的是你可以扩展类只有当它是可见的!)。 让我们这样说吧:

  • 受保护的顶层类将在其包中的类中可见。
  • 现在使它在包(子类)之外可见是有点混乱和棘手。 哪些类应该被允许inheritance我们的受保护的类?
  • 如果所有的类都允许子类化,那么它将类似于公共访问说明符。
  • 如果没有,那么它是类似于默认。

由于没有办法限制这个类只被less数类所inheritance(我们不能限制类只能被包中的所有可用类/包之外的类所inheritance),所以没有使用受保护的访问说明符为顶级课程。 因此这是不允许的。

public class A { protected class B { } } 

定义受保护的字段使得该字段可以通过inheritance(仅在子类中)在包内以及包外部访问。

所以,如果允许我们创build一个类,那么我们可以非常容易地在包内部访问它,但是为了在包之外访问这个类,我们首先需要扩展这个包含它的类的实体。

而且由于一个包不能被扩展(可以被导入),定义一个受保护的类将再次使它成为package-private,类似于将其定义为默认,我们已经可以做到这一点。 因此,定义一个类的私有没有好处,它只会使事情变得模糊。

有关更多信息,请阅读为什么外部Java类不能是私有的或受保护的

在“public,private,protected和default”四个访问修饰符中,一个类只能有public和default修饰符。

如果你有公开课,你可以随时随地使用它,这很简单。 你可以在任何包中导入它并开始使用它。

但是,如果你有一个没有修饰符/默认的类,那么你甚至不能将它导入到另一个包中。 例如,你有类:DefaultClass.java

 package home; class DefaultClass{ .. } 

另一个类作为另一个包中的TestingIt.java。

 package office; import home. 

在上面代码中尝试导入home.DefaultClass的那一刻,您将意识到我们的DefaultClass不能被导入。 一个房子外面的包是不可见的。 我们不能在这个TestingIt.java文件中导入它。 为什么不? 因为默认=限于它自己的包。

而现在来到你的问题:“为什么类没有保护访问修饰符? 我认为它可能是因为它不会比默认/无修饰符类。 即使“受保护的类”是可能的,也不能像“默认/无修饰符类”那样在另一个包中导入它。

你可以在同一个软件包中使用它们,但是一旦你导入它们,它们在同一个软件包中的function将完全相同。 因此,就类的访问修饰符而言,protected和default是相同的。

@Nikita Rybak答案有很好的一面,但缺乏细节,我不能简单地得到这个想法,没有深思熟虑,以下是我的想法,现在我应该完全明白原因。

四个访问修饰符,假设第一个级别是公开的,第四个级别是私有的(基于这个表格 )。 我们应该知道的第一件事是为什么class级不能在顶层定义为私人。

所以如果“私人类foo”(一个私人成员定义,即类本身是一个成员)允许,什么是外(包含成员)? 文件范围? 不,文件外层是毫无意义的,因为即使单个文件中的多个类也会被编译成单独的类文件。 所以外面是包 。 但是第三级的默认访问修饰符已经意味着“包私有 ”。 所以第四级私人访问修改器将不会被使用/允许。

嵌套的私人类是允许的,因为直接的外层是类,而不是包, 例如 :

 class PrivateNestedMain { private static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } } 

现在如果“受保护的类foo”允许? 受保护的主要特征是子类,所以外(包)应该(由于范围,但仍然是可选的)提供子类的风格 ,即子包,或者package A extends package B ,但是我们不知道这样的东西。 因此, 被保护的顶层(即没有这样的子包的东西)不能充分利用全部潜能(主范围是子类范围),但是保护可以在外层是类的嵌套类中充分发挥潜能即可以是子类)

 class ProtectedNestedMain { protected static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } } 

请注意,上面所说的“不能充分发挥潜力”,因为它不能仅仅因为没有外部的子类, 这就意味着实际上是被保护的因此它不能到达子类范围, 所以避免重复包装的工作只是一个select的问题如果外层不是子类 ,请参阅下面的内容。

我的困惑主要是由https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html上的着名表格引起的:;

在这里输入图像说明

如果允许第一级(公共)和第三级(私人包装),那么在地球上二级(受保护)是不允许的?

公众支持子类容易误导。 阅读这张表的正确方法是

公共支持子类如果外部有子类特征。

同样的误导适用于pacakage-private,pacakage-private不支持子类( N in cell)并不意味着子类概念适用于外层。

这意味着如果子类特性在外层不可用,我们应该忽略子类列:

在这里输入图像说明

正如我们现在所看到的那样,受保护的和封装私有的都是现在的同一级别( YYN ),为什么不允许中间级别的混淆。 总的来说,Java只是select了package-private over保护以避免混淆( 这只是一个select的问题 ,但是受保护的主要特性是子类,所以package-private是优越的), 结果 ,顶层只允许使用2个访问修饰符:

在顶层 – 公共或包私有(没有明确的修饰语)。

保护与公众不相似。 受保护的同时具有包级别访问权限,只能通过inheritance来在包之外访问。如果一个类在包之外声明A从其他包中插入一个类(通过使用INHERITANCE的受保护方法),则可以访问此类的方法B有保护方法,但从这个类派生的子类,即A不能访问受保护的方法。

例:

 package 2; class B { protected void method1() { } } package 1; import 2.B; class A extends B { //can access protected method } class C extends A { //can't access the protected method } 

“protected”的行为=“默认”行为+“在任何包中的任何子类中使用”。

无论如何,我们有类的默认访问修饰符,唯一的好处,我们可以从受保护的访问修饰符是: – 在任何包通过子类使用它。 但是对于子类,父类“受保护”类的可见性将是私有的。 所以它不能被访问。 基本上,如果你有一个受保护的顶级类,没有外部类可以通过inheritance子类来访问。 所以保护一个顶级的课程是没有意义的。