101

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

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

4

13 回答 13

112

因为没有意义。

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

不过,您可以将嵌套类和内部类声明为受保护或私有。

于 2010-10-06T04:49:13.493 回答
46

如您所知,默认用于包级访问,protected 用于包级和非包类,但它扩展了此类(这里要注意的是,只有当它可见时才能扩展该类!)。让我们这样说:

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

由于无法限制此类仅由少数类子类化(我们不能限制类仅由包中/包外部的所有可用类中的少数类继承),因此不使用受保护的访问说明符对于顶级课程。因此是不允许的。

于 2013-04-30T05:50:19.130 回答
15
public class A
{
    protected class B
    {
    }
}
于 2010-10-06T04:51:13.430 回答
4

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

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

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

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

于 2016-10-12T10:31:47.817 回答
3

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

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

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

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

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

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

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

请注意,上面所说的“不能充分发挥潜力”是因为它不能达到子类范围,仅仅因为没有外部子类,这意味着实际上 protected 可以是允许的,避免重复包的工作只是一个选择问题-private 如果外部不能子类化,请参见下文。

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

在此处输入图像描述

如果允许 1 级(公共)和 3 级(包私有),那么究竟如何不允许介于 2 级(受保护)之间?

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

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

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

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

在此处输入图像描述

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

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

于 2016-05-31T20:37:37.750 回答
1

受保护的与公开的不同。受保护的具有包级别访问权限,并且只能通过继承在包外部访问。如果一个类说包外的 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
}
于 2015-03-27T17:03:04.337 回答
1

如果一个外部类是由protected声明的,我想你希望这个类只能从同一个包及其子类但不同的包访问。但是,不可能为受保护的类创建子类,因为当您编写“狗类扩展动物”时,因为受保护的“动物”只能被其子类访问,显然“狗”不是“动物”子类.

所以受保护的外部类与(默认)外部类相同!

于 2020-09-28T10:02:03.533 回答
0

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

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

于 2014-07-03T15:43:14.993 回答
0

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

类被定义为受保护---> 它不能从外部包扩展(不可见)。

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

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

注意:嵌套或内部类可以定义为受保护的或私有的。

*:探索受保护的关键字,对于这个答案,我做得很简洁。

于 2018-03-14T08:42:18.240 回答
0

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

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

由于无法限制此类仅由少数类子类化(我们不能限制类仅由包中/包外部的所有可用类中的少数类继承),因此不使用受保护的访问说明符对于顶级课程。因此是不允许的。

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

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

于 2018-04-12T02:28:30.237 回答
0

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

JVM 不会访问受保护类的答案是,因为受保护的字段可以在同一个包中访问,或者只能通过继承访问不同的包,并且 JVM 没有以某种方式编写,以便它将继承类。希望这能满足这个问题:)

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

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

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

于 2018-06-14T12:55:20.190 回答
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 
}
于 2018-09-01T19:22:12.097 回答
0

内部类允许使用受保护的修饰符。但是仍然不能从扩展外部类的类中构造这个内部类的实例。只有当构造代码在同一个包中时,编译器才允许。但是,protected修饰符对默认可访问性有什么影响?因此,从我的角度来看,顶级类根本不允许使用受保护的修饰符,并且在嵌入式类上也没有意义。

于 2022-01-19T13:19:54.403 回答