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


89

为什么我们不能将一个类定义为 protected

我知道我们做不到,但是为什么呢?应该有一些特定的原因。


3
那会是什么做的,如果你申报一类保护?

1
我认为这是您正在寻找的东西:stackoverflow.com/questions/2534733/java-protected-classes :D
dewijones92 2013年

2
我们只说为什么不能保护外部类?内部类可以受到保护。
Number945 '18

Answers:


101

因为这没有意义。

受保护的类成员(方法或变量)类似于package-private(默认可见性),除了它也可以从子类访问。
由于在Java中没有“子包”或“包继承”这样的概念,因此声明受保护的类或包私有的将是同一回事。

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


>由于Java中没有“子包”或“包继承”这样的概念,因此声明受保护的类或包私有的将是同一回事。为什么受保护的类具有与package-private相同的可见性?与公众不同吗?谢谢。
yaromir 2014年

@Nikita Ryback您能解释什么是subPackage或包继承吗?我仍不清楚为什么在顶级类中使用了protected。
App Kart 2015年

当您声明类成员为受保护对象时,其可见性是同一包(称为包访问)和Subclassess上的类。如果尝试从其他程序包的外部类访问,则此受保护的方法成员不可见。
kelgwiin 2015年

@kelgwiin我相信您不应该混合使用类和成员的访问修饰符。因为两者是不同的。虽然类允许将自己修改为public或default,但成员可以修改为public,private,protected和default。
sharhp

2
“因为没有意义”-这是一个相当大胆的声明。它没有用Java定义,但是确实存在类似的东西。例如,open在Kotlin中,它允许在当前程序包之外进行子类化(可以想象protected在Java中可以避免这种情况,默认情况相反)。
拉斐尔

41

如您所知,默认值是针对程序包级别的访问,而受保护的则是针对程序包级别以及非程序包的类,但这扩展了该类(这里要指出的是,只有在可见的情况下,您才可以扩展该类!)。让我们这样说:

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

由于没有办法限制仅由少数几个类继承该类(我们不能限制仅在一个包/一个包之外的所有可用类中,只有少数几个类继承该类),因此不使用受保护的访问说明符对于顶级课程。因此,这是不允许的。


3
“现在使受保护的类在包(子类)的外部可见是一个令人困惑和棘手的问题。应该允许哪些类继承我们的受保护的类?如果允许所有的类成为子类,那么它将类似于公共访问说明符。” 确实帮助我理解了为什么受保护的类没有意义的问题:)
user1338998 2014年


3

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

四个访问修饰符,假定第一级是公共的,第四级是私有的(基于此顺序)。我们应该知道的第一件事是为什么不能在顶级将类定义为私有。

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

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

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

现在,如果“受保护的类foo”允许怎么办?受保护的主要特征是子类,因此external(package)应该(由于作用域而定,但仍是可选的)提供子类的样式,即sub-package或package A extends package B,但我们不知道这种事情。因此,受保护的不能在外部是包的顶层使用最大的潜力(主要作用域是子类范围的)(即没有此类子包的东西),但是受保护的可以在外部是包的嵌套类中使用全部的潜力(即可以是子类)

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

请注意,上述“不能充分利用潜力”是因为它不能达到子类范围,这仅仅是因为没有外部子类,这意味着可以允许实际上受保护这是避免重复包装工作的唯一选择-private(如果外部不能子类化),请参见下文。

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

在此处输入图片说明

如果允许第一级(公共)和第三级(打包-私有),那么到底如何不允许第二级(受保护)之间?

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

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

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

这意味着如果外部没有子类功能,则我们应该忽略“子类”列:

在此处输入图片说明

正如我们现在所看到的,protected和package-private现在都处于同一级别(YYN),对于为什么不允许在中间级别之间再也没有混淆。总体而言,Java只选择package-private而不是protected以避免混淆(这只是选择的问题,但是受保护的主要特征是子类,因此package-private更好),结果是顶层仅允许使用2个访问修饰符:

在顶层(公共或包私有)(无显式修饰符)。


3

定义受保护的字段将使该字段只能通过继承在包内部和包外部(仅在子类内部)访问。

因此,如果允许我们对一个类进行保护,那么我们可以很容易地在包中访问它,但是要在包外部访问该类,我们首先需要扩展定义该类的实体(即它的包)。

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

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


3
请披露任何隶属关系,请勿将网站用作通过发布来推广您的网站的方式。请参阅如何写一个好的答案?

1

受保护与众不同。受保护的对象具有包级别的访问权限,并且只能通过继承在包外部访问。具有受保护的方法,但派生自此类的子类,即A无法访问受保护的方法。与public相反。

例:

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
}

0

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

无论如何,我们都有用于类的默认访问修饰符,从受保护的访问修饰符中获得的唯一好处是:-通过子类在任何包中使用它。但是对于子类,父级“受保护”类的可见性将是私有的。因此无法访问。基本上,如果您有受保护的顶级类,则没有任何外部类可以通过对它进行子类化来获得访问权限。因此,为顶级类提供保护是没有意义的。


0

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

定义为保护--->无法扩展从外部包(不可见)。

而且,如果无法扩展它,则将其保留为受保护是没有意义的,因为那样它将成为默认值。允许访问权限。

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

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

*:探索受保护的关键字,为此答案,我使其简洁。


0

@ Akash5288的答案对我来说毫无意义:

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

由于没有办法限制仅由少数几个类继承该类(我们不能限制仅在一个包/一个包之外的所有可用类中,只有少数几个类继承该类),因此不使用受保护的访问说明符对于顶级课程。因此,这是不允许的。

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

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


0

对这个问题有意义的是,JVM是用C(Sun JVM)和C ++(oracle JVM)编写的,因此在编译过程中,我们将从Java文件中创建.class文件,如果我们使用Protected关键字声明了一个类, JVM将无法访问它。

为何JVM无法访问受保护的类的答案是,因为受保护的字段只能通过继承在同一包内访问,也可以通过继承来访问不同的包,而JVM的编写方式却使其无法继承will类。希望这能满足这个问题:)

同样,顶级类也不能是私有的。解释如下:

那么,如果我们将定义一个私有类,该类将只能在定义它的实体(在我们的情况下是它的包)内访问,该怎么办?

因此,定义对类的私有访问将使它可以在默认关键字已为我们使用的同一个程序包中进行访问,因此,将类定义为私有将无益,只会使事情变得模棱两可。


0

protected表示成员可以被同一包中的任何类以及子类访问,即使它们位于另一个包中。

例:

package a;
class parent{
 protected void p();
}
package b;
import a.p;
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 
}

0

如果外部类是由protected声明的,则我想您只能从相同的包及其子类但可以从不同的包访问该类。但是,无法为受保护的类创建子类,因为当您编写“狗扩展动物类”时,由于受保护的“动物”只能由其子类访问,显然,“狗”不是“动物”子类。

因此,受保护的外部类与(默认)外部类相同!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.