在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?
当前回答
私人:仅限上课
默认值(无修饰符):对类和包的访问受限
受保护:对类、包和子类的访问受限(包内部和外部)
公共:可访问类、包(所有)和子类。。。简而言之,无处不在。
其他回答
区别可以在已经提供的链接中找到,但使用哪一个链接通常取决于“最少知识原则”。只允许所需的最小可见性。
官方教程可能对您有所帮助。
Class | Package | Subclass (same pkg) |
Subclass (diff pkg) |
World | |
---|---|---|---|---|---|
public |
+ | + | + | + | + |
protected |
+ | + | + | + | |
no modifier | + | + | + | ||
private |
+ |
+:可访问空白:不可访问
它实际上比简单的网格显示要复杂一些。网格告诉是否允许访问,但访问到底由什么构成?此外,访问级别以复杂的方式与嵌套类和继承交互。
“默认”访问(由缺少关键字指定)也称为包专用。异常:在接口中,没有修饰符表示公共访问;禁止公共以外的修饰语。枚举常量始终是公共的。
总结
是否允许使用此访问说明符访问成员?
成员是私有的:仅当成员与调用代码在同一类中定义时。成员是包专用的:仅当调用代码位于成员的直接封装包内时。成员受保护:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。成员公开:是的。
访问说明符应用于什么
局部变量和形式参数不能采用访问说明符。由于根据范围界定规则,外部无法访问它们,因此它们实际上是私有的。
对于顶级作用域中的类,只允许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方法可访问性?
平民的如果用public声明类成员,则可以从任何地方访问它受保护的如果用关键字protected声明类成员,则可以从相同的类成员、同一包内的外部类成员和继承的类成员访问该类成员。如果类成员受到保护,则不能从外部包类访问它,除非外部包类被继承,即扩展其他包超类。但是,受保护的类成员始终可用于相同的包类,无论是否继承了相同的包类别违约在Java中,默认值不是访问修饰符关键字。如果声明的类成员没有任何访问修饰符关键字,那么在这种情况下,它被视为默认成员。默认类成员始终可用于相同的包类成员。但即使外部类是与受保护成员不同的子类,外部包类成员也不能访问默认类成员私有的如果用关键字protected声明了类成员,那么在这种情况下,它只对相同的类成员可用
作为经验法则:
private:类范围。默认(或包专用):包范围。protected:包范围+子级(类似于包,但我们可以从不同的包中对其进行子类化)。受保护的修饰符始终保持“父子”关系。公众:无处不在。
因此,如果我们将访问权分为三种权利:
(D) direct(从同一类内的方法调用,或通过“this”语法调用)。(R) reference(使用对类的引用或通过“dot”语法调用方法)。(一) 继承(通过子类化)。
那么我们有一个简单的表格:
+—-———————————————+————————————+———————————+
| | Same | Different |
| | Package | Packages |
+—————————————————+————————————+———————————+
| private | D | |
+—————————————————+————————————+———————————+
| package-private | | |
| (no modifier) | D R I | |
+—————————————————+————————————+———————————+
| protected | D R I | I |
+—————————————————+————————————+———————————+
| public | D R I | R I |
+—————————————————+————————————+———————————+
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap