在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?
当前回答
当谈到访问修饰符时,我们很容易理解,非常简单的规则包括它们。
专用访问修饰符用于:-仅同一类
默认Access修饰符用于:-仅同一类/同一包子类
Protected Access修饰符用于:-同一类/同一包子类/同包非子类/不同包子类
公共访问修饰符用于:-我们可以在任何地方使用(相同的类/相同的包子类/相同包非子类/不同的包子类别/不同包非子类别)
其他回答
它实际上比简单的网格显示要复杂一些。网格告诉是否允许访问,但访问到底由什么构成?此外,访问级别以复杂的方式与嵌套类和继承交互。
“默认”访问(由缺少关键字指定)也称为包专用。异常:在接口中,没有修饰符表示公共访问;禁止公共以外的修饰语。枚举常量始终是公共的。
总结
是否允许使用此访问说明符访问成员?
成员是私有的:仅当成员与调用代码在同一类中定义时。成员是包专用的:仅当调用代码位于成员的直接封装包内时。成员受保护:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。成员公开:是的。
访问说明符应用于什么
局部变量和形式参数不能采用访问说明符。由于根据范围界定规则,外部无法访问它们,因此它们实际上是私有的。
对于顶级作用域中的类,只允许public和package private。这种设计选择大概是因为受保护和私有在包级别是冗余的(没有包的继承)。
所有访问说明符都可以在类成员(构造函数、方法和静态成员函数、嵌套类)上使用。
相关:Java类可访问性
顺序
访问说明符可以严格排序
public>protected>package private>private
这意味着公共提供的访问最多,而私人提供的访问最少。对私有成员的任何引用对包私有成员也是有效的;对包私有成员的任何引用都对受保护成员有效,依此类推。(将受保护成员的访问权限授予同一包中的其他类被认为是错误的。)
笔记
允许类的方法访问同一类的其他对象的私有成员。更准确地说,类C的方法可以访问C的任何子类的对象上的C的私有成员。Java不支持仅通过类而通过实例限制访问。(与Scala相比,Scala确实支持使用private[this]。)您需要访问构造函数来构造对象。因此,如果所有构造函数都是私有的,那么类只能由类中的代码(通常是静态工厂方法或静态变量初始化器)来构造。对于包私有或受保护的构造函数也是如此。只有私有构造函数也意味着类不能在外部子类化,因为Java需要子类的构造函数隐式或显式调用超类构造函数。(但是,它可以包含一个将其子类化的嵌套类。)
内部类
您还必须考虑嵌套范围,例如内部类。复杂性的一个例子是内部类具有成员,这些成员本身可以接受访问修饰符。因此,您可以拥有一个具有公共成员的私有内部类;可以访问该成员吗?(见下文。)一般规则是查看范围并递归地思考,看看是否可以访问每个级别。
然而,这非常复杂,有关详细信息,请参阅Java语言规范。(是的,过去曾出现过编译器错误。)
要了解这些交互的方式,请考虑以下示例。“泄漏”私有内部类是可能的;这通常是一个警告:
class Test {
public static void main(final String ... args) {
System.out.println(Example.leakPrivateClass()); // OK
Example.leakPrivateClass().secretMethod(); // error
}
}
class Example {
private static class NestedClass {
public void secretMethod() {
System.out.println("Hello");
}
}
public static NestedClass leakPrivateClass() {
return new NestedClass();
}
}
编译器输出:
Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
Example.leakPrivateClass().secretMethod(); // error
^
1 error
一些相关问题:
包私有类内的Java方法可访问性?
官方教程可能对您有所帮助。
Class | Package | Subclass (same pkg) |
Subclass (diff pkg) |
World | |
---|---|---|---|---|---|
public |
+ | + | + | + | + |
protected |
+ | + | + | + | |
no modifier | + | + | + | ||
private |
+ |
+:可访问空白:不可访问
当谈到访问修饰符时,我们很容易理解,非常简单的规则包括它们。
专用访问修饰符用于:-仅同一类
默认Access修饰符用于:-仅同一类/同一包子类
Protected Access修饰符用于:-同一类/同一包子类/同包非子类/不同包子类
公共访问修饰符用于:-我们可以在任何地方使用(相同的类/相同的包子类/相同包非子类/不同的包子类别/不同包非子类别)
这是该表的一个更好的版本,其中还包括一个模块列。
解释
私有成员(i)只能在声明的同一类中访问。没有访问修饰符(j)的成员只能在同一包中的类中访问。受保护的成员(k)可以在同一包中的所有类和其他包中的子类中访问。公共成员(l)对所有类都是可访问的(除非它驻留在不导出声明它的包的模块中)。
要选择哪个修饰符?
访问修饰符是一种帮助您防止意外破坏封装(*)的工具。问问自己,您是否希望成员是类、包、类层次结构的内部成员,或者根本不是内部成员,并相应地选择访问级别。
示例:
长字段internalCounter可能应该是私有的,因为它是可变的,并且是实现细节。只应在工厂类中实例化的类(在同一个包中)应具有包限制构造函数,因为不可能从包外部直接调用它。应保护在呈现之前调用并用作子类中钩子的内部void beforeRender()方法。从GUI代码调用的void saveGame(File dst)方法应该是公共的。
(*)封装到底是什么?
当你想到访问修饰符时,你可以这样想(适用于变量和方法):
public-->可从任何位置访问private-->只能在声明它的同一类中访问
现在,当涉及到默认和受保护时,就会出现混乱
默认-->不存在访问修饰符关键字。这意味着它严格在类的包中可用。在该包之外,任何地方都无法访问。
protected-->略低于默认值,并且除了相同的包类之外,它可以由声明的包之外的子类访问。
推荐文章
- Intellij IDEA Java类在保存时不能自动编译
- 何时使用Mockito.verify()?
- 在maven中安装mvn到底做什么
- 不可变与不可修改的集合
- 如何在JSON中使用杰克逊更改字段名
- GSON -日期格式
- 如何从线程捕获异常
- 无法解析主机"<URL here>"没有与主机名关联的地址
- 如何在Java中打印二叉树图?
- String.format()在Java中格式化双重格式
- com.jcraft.jsch.JSchException: UnknownHostKey
- Java中的操作符重载
- 如何加速gwt编译器?
- 在Hibernate中重新连接分离对象的正确方法是什么?
- 应该……接住环内还是环外?