我知道这是一个愚蠢的问题,但我仍有疑问需要清除。
我的问题是,为什么我们不能将课程定义为protected
?
我知道我们不能,但为什么?应该有一些具体的原因。
答案 0 :(得分:82)
因为没有意义。
受保护的类成员(方法或变量)就像package-private(默认可见性),除了它也可以从子类访问。 由于Java中没有'subpackage'或'package-inheritance'这样的概念,因此声明class protected或package-private将是同样的事情。
但是,您可以将嵌套和内部类声明为protected或private。
答案 1 :(得分:32)
正如您所知,默认是针对包级访问,而protected是针对包级别加非包类,但是扩展了这个类(这里要注意的是,只有在可见时才可以扩展类!)。 让我们这样说吧:
由于没有办法限制这个类仅由少数类进行子类化(我们不能限制类只被包中/包外的所有可用类中的几个类继承),所以没有使用顶级类的受保护访问说明符。因此不允许。
答案 2 :(得分:13)
public class A
{
protected class B
{
}
}
答案 3 :(得分:3)
定义受保护的字段使得该字段只能通过继承在包内以及包外部访问(仅在子类中)。
因此,如果我们允许对类进行保护,那么我们可以非常容易地在包内访问它,但是为了访问包外的类,我们首先需要扩展定义了这个类的实体,即它的包。
由于无法扩展包(可以导入),因此定义受保护的类将再次使其成为package-private,类似于将其定义为我们已经可以执行的默认值。 因此,定义私有类没有任何好处,只会使事情变得模棱两可。
有关详细信息,请参阅Why an outer Java class can’t be private or protected
答案 4 :(得分:2)
@Nikita Rybak answer有好点,但缺乏细节,我不能简单地在没有深入思考的情况下得到这个想法,以下是我的想法,现在我应该完全理解其中的原因。
四个访问修饰符,假设第一级是公共级,第四级是私有级(依次基于此table)。我们应该知道的第一件事是为什么类不能在顶层定义为私有。
因此,如果“私有类foo”(私有成员定义,即类本身是成员)允许,外部(包含成员)是什么? 文件范围?不,文件外部没有意义,因为即使单个文件中的多个类也会编译成单独的类文件。 所以外部是包。但是第3级默认访问修饰符已经意味着“package-private ”。因此不会使用/允许第4级私有访问修饰符。
但嵌套私有类是允许的,因为直接外部是类,而不是包,e.g.:
class PrivateNestedMain {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
现在如果“受保护的类foo”允许怎么办? protected 主要特征是子类,所以外部(包)应该(由于最大范围,但仍然是可选的)提供样式的子类,即子包,或package A extends package B
,但我们不知道这件事。所以 protected不能在顶层使用完全潜在的(主范围是子类范围的),外层是包(即没有这样的子包东西),但是受保护的可以在外层的嵌套类中使用全部潜力是类(即可以是子类):
class ProtectedNestedMain {
protected static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
请注意,上面所说的“不能使用全部潜力”,因为它无法达到子类范围,因为没有外部子类,这意味着实际上受到保护可以允许,如果外部不是子类,那么避免重复package-private的工作只是一个选择问题,见下文。
我的困惑主要是由https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html的着名表格引起的:
如果允许第1级(公共级)和第3级(包私有),那么中间的第2级(受保护)如何被禁止?
公共支持子类很容易产生误导。阅读此表的正确方法是
公共支持子类,如果外部具有子类特征。
同样的误导性适用于package-private,package-private不支持子类(单元格中的 N )并不意味着子类概念适用于外部。
这意味着如果子类功能在外部不可用,我们应该忽略子类列:
正如我们现在所看到的,protected和package-private现在都是相同的级别( Y-Y-N ),不再混淆为什么不允许中间级别。总的来说,Java只选择包私有保护以避免混淆(它只是一个选择问题,但受保护的主要特征是子类,因此包私有优势),和result,顶层只允许2个访问修饰符:
在顶层 - public或package-private(没有显式修饰符)。
答案 5 :(得分:1)
受保护与公众不相似。受保护具有包级访问权限,只能通过继承访问包外部。如果一个类在包外面说一个INHERITS来自其他包的类(通过使用INHERITANCE使用protected方法),它可以访问此类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
}
答案 6 :(得分:0)
“protected”的行为=“默认”的行为+“在任何包的任何子类中使用它”。
无论如何,我们有类的默认访问修饰符,只有我们可以从受保护的访问修饰符得到的优点是: - 通过子类化在任何包中使用它。但对于子类,父“受保护”类的可见性将是私有的。所以它无法访问。基本上,如果你有一个受保护的顶级类,没有外部类可以通过子类化来获得访问权限。因此,保护顶级课程毫无意义。
答案 7 :(得分:0)
受保护:仅对包级别*可见。
类已定义受保护 ---> 无法扩展来自外部包(不可见)。
如果无法扩展,那么将其保留为 protected 是没有意义的,因为它将成为默认访问权限。
同样适用于私有定义的类。
注意:可以定义嵌套或内部类 protected 或 private 。
* :探索受保护的关键字,对于这个答案,我简明扼要。
答案 8 :(得分:0)
@ Akash5288的回答对我没有意义:
如果允许所有类都是子类,那么它将类似于公共访问说明符。
由于没有办法限制这个类仅由少数类进行子类化(我们不能限制类只被包中/包外的所有可用类中的几个类继承),所以没有使用顶级类的受保护访问说明符。因此不允许。
然后,您可以将相同的逻辑应用于受保护的方法和变量,然后它们也“类似于公共”。包之外的所有类都可以扩展我们的公共类并使用其受保护的方法。为什么将方法和变量限制为扩展类可以,但限制整个类不正常? “与公众相似”并非“与公众相同”。我的解释是允许受保护的类是完全正确的,因为允许受保护的方法是可以的。
答案“你不能扩展你无法访问/看到的课程”更合乎逻辑。
答案 9 :(得分:0)
这个问题有意义的是,JVM是用C(Sun JVM)和C ++(oracle JVM)编写的,所以在编译期间,我们将从我们的java文件中创建.class文件,如果我们声明一个类使用Protected关键字,JVM将无法访问它。
JVM无法访问受保护类的原因是,因为受保护的字段只能在同一个包中访问,或者只能通过继承访问不同的包,而JVM不是以某种方式编写的,因此它将继承类。 希望这能满足这个问题:)
同样,顶级课程也不能成为私人课程。说明如下:
那么如果我们要定义一个私有类会发生什么,该类只能在定义它的实体中访问,在我们的例子中是它的包?
因此,定义对类的私有访问将使其可以在默认关键字已经为我们执行的相同包中访问,因此定义类私有没有任何好处,它只会使事情变得模棱两可。
答案 10 :(得分: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
}
答案 11 :(得分:0)
如果一个外部类是由protected声明的,我想您希望该类只能从相同的包及其子类访问,而不能从不同的包访问。但是,无法为受保护的类创建子类,因为在编写“狗扩展动物类”时,由于受保护的“动物”只能由其子类访问,显然,“狗”不是“动物”子类
因此受保护的外部类与(默认)外部类相同!