为什么不能将类定义为受保护的?

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

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

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

因为没有意义。

受保护的类成员(方法或变量)就像package-private(默认可见性),除了它也可以从子类访问。
由于Java中没有’subpackage’或’package-inheritance’这样的概念,因此声明class protected或package-private将是同样的事情。

但是,您可以将嵌套和内部类声明为protected或private。

如您所知,默认是针对包级访问,而protected是针对包级别加非包类,但是扩展了这个类(这里要注意的是,只有在可见的情况下才可以扩展类!)。 我们这样说吧:

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

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

 public class A { protected class B { } } 

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

因此,如果允许我们创建一个受保护的类,那么我们可以非常容易地在包内访问它,但是为了访问包外的类,我们首先需要扩展定义了这个类的实体,即它的包。

并且由于无法扩展包(可以导入),因此定义受保护的类将再次使其成为package-private,这类似于将其定义为我们已经可以执行的默认操作。 因此,定义私有类没有任何好处,它只会使事情变得模棱两可。

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

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

如果你有一个公共课,你可以在任何你想要的地方使用它,这很简单。 您可以在任何包中导入它并开始使用它。

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

 package home; class DefaultClass{ .. } 

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

 package office; import home. 

当您尝试在上面的代码中导入home.DefaultClass时,您将意识到我们的DefaultClass无法导入。 家庭以外的包裹不可见。 我们无法在此TestingIt.java文件中导入它。 为什么不? 因为default =仅限于自己的包。

现在提出你的问题“为什么一个类不能保护访问修饰符?” 我认为这可能是因为它与默认/无修饰符类没什么区别。 即使“受保护的类”是可能的,您也无法将其导入到另一个包中,就像“默认/无修饰符类”一样。

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

@Nikita Rybak回答有好点但缺乏细节,我不能简单地在没有深入思考的情况下得到这个想法,以下是我的想法,现在我应该完全理解其中的原因。

四个访问修饰符,假设第一级是公共级,第四级是私有级(依次按此表 )。 我们应该知道的第一件事是为什么类不能在顶层定义为私有。

因此,如果“私有类foo”(私有成员定义,即类本身是成员)允许,外部(包含成员)是什么? 文件范围? 不,文件外部是没有意义的,因为即使单个文件中的多个类也将编译成单独的类文件。 因此外包装 。 但是第3级默认访问修饰符已经意味着“包私有 ”。 因此不会使用/允许第4级私有访问修饰符。

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

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

现在如果“受保护的类foo”允许怎么办? protected main特性是子类,所以外部(包)SHOULD(由于最大范围,但仍然是可选的)提供子类的样式 ,即子包,或package A extends package B ,但我们不知道这样的事情。 所以受保护不能在顶层使用完全潜力(主范围是子类范围),外层是包(即没有这样的子包东西),但受保护可以在外层为类的嵌套类中使用全部潜力(即可以是子类)

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

注意上面说的“不能使用全部潜力”,因为它无法达到子类范围,因为没有外部子类,这意味着实际上可以被允许这只是一个选择,避免重复包的工作-private if outer不是subclassable ,见下文。

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

在此处输入图像描述

如果允许第一级(公共)和第三级(包私有),那么中间的第二级(受保护)如何不被允许?

公共支持子类很容易产生误导。 阅读此表的正确方法是

公共支持子类,如果外部具有子类function。

同样的误导性适用于pacakage-private,pacakage-private不支持子类(单元格中的N )并不意味着子类概念适用于外部。

这意味着如果子类function在外部不可用,我们应该忽略Subclass列:

在此处输入图像描述

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

在顶层 – public或package-private(没有显式修饰符)。

受保护与公众不相似。 受保护具有包级别访问权限,只能通过inheritance访问包外部。如果一个类在包外面说一个INHERITS来自其他包的类(使用受保护的方法,使用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 } 

“受保护”的行为=“默认”的行为+“在任何包中的任何子类中使用它”。

无论如何,我们有类的默认访问修饰符,只有我们可以从受保护的访问修饰符得到的优点是: – 通过子类化在任何包中使用它。 但对于子类,父“受保护”类的可见性将是私有的。 所以它无法访问。 基本上如果你有一个受保护的顶级类,没有外部类可以通过子类化来获得访问权限。 所以对顶级课程的保护是没有意义的。

受保护 :仅对包级别*可见。

class被定义protected —>它不能从外包扩展 (不可见)。

如果它不能被扩展,那么将它保持为受保护是没有意义的,因为它将成为允许的默认访问。

同样适用于私有定义的类。

注意:嵌套或内部类可以定义为protectedprivate

* :探索受保护的关键字,对于这个答案,我简明扼要。

@ Akash5288的答案对我没有意义:

如果允许所有类都是子类,那么它将类似于公共访问说明符。

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

然后,您可以将相同的逻辑应用于受保护的方法和变量,然后它们也“类似于公共”。 包之外的所有类都可以扩展我们的公共类并使用其受保护的方法。 为什么将方法和变量限制为扩展类可以,但限制整个类不正常? “与公众相似”并非“与公众相同”。 我的解释是,允许受保护的类是完全正确的,因为允许受保护的方法很好。

答案“你不能扩展你无法访问/看到的类”更合乎逻辑。

对这个问题有意义的是,JVM是用C(Sun JVM)和C ++(oracle JVM)编写的,所以在编译期间,我们将从java文件中创建.class文件,如果我们声明一个带有Protected关键字的类那么JVM就不会访问它。

JVM无法访问受保护类的原因是,因为受保护的字段只能在同一个包中访问,或者只能通过inheritance访问不同的包,而JVM不是以某种方式编写的,因此它将inheritance类。 希望这满足这个问题:)

同样,顶级课程也不能是私人课程。 解释如下:

那么如果我们要定义一个私有类会发生什么,该类只能在定义它的实体中访问,在我们的例子中它是它的包?

因此,定义对类的私有访问将使其可以在默认关键字已经为我们执行的相同包中访问,因此定义类私有没有任何好处,它只会使事情变得模糊。

 protected means that the member can be accessed by any class in the same package and by sub classes even if they are in another packages. example: package a; class parent{ protected void p(); } package b; import ap; class child extends parent{ //you can access method which is protected in the parent in the child } class another extends child { //here you can not access the protected method }