在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?
当前回答
作为经验法则:
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 |
+—————————————————+————————————+———————————+
其他回答
这是该表的一个更好的版本,其中还包括一个模块列。
解释
私有成员(i)只能在声明的同一类中访问。没有访问修饰符(j)的成员只能在同一包中的类中访问。受保护的成员(k)可以在同一包中的所有类和其他包中的子类中访问。公共成员(l)对所有类都是可访问的(除非它驻留在不导出声明它的包的模块中)。
要选择哪个修饰符?
访问修饰符是一种帮助您防止意外破坏封装(*)的工具。问问自己,您是否希望成员是类、包、类层次结构的内部成员,或者根本不是内部成员,并相应地选择访问级别。
示例:
长字段internalCounter可能应该是私有的,因为它是可变的,并且是实现细节。只应在工厂类中实例化的类(在同一个包中)应具有包限制构造函数,因为不可能从包外部直接调用它。应保护在呈现之前调用并用作子类中钩子的内部void beforeRender()方法。从GUI代码调用的void saveGame(File dst)方法应该是公共的。
(*)封装到底是什么?
Java访问修改
访问修饰符可适用于类、字段[About]和方法。尝试访问、子类化或重写此。
通过类访问字段或方法。继承与开闭原理〔关于〕后继类(子类)访问修饰符可以是任意的。后继方法(重写)访问修饰符应相同或展开
顶级类(一级范围)可以是公共的,也可以是默认的。嵌套类[About]可以包含其中任何一个
包未应用于包层次结构
[Swift访问修饰符]
此页很好地描述了受保护的默认访问修饰符(&D)
....受保护:受保护的访问修饰符有点棘手,可以说是默认访问修饰符的超集。就同一包中的访问而言,受保护的成员与默认成员相同。不同的是,受保护的成员也可以访问声明成员的类的子类,这些子类位于父类所在的包之外。
但是,这些受保护的成员“只能通过继承在包外部访问”。即,您可以直接访问某个类的子类中的受保护成员,就像该成员存在于子类本身中一样。但是,通过使用父类的引用,该受保护成员在包外部的子类中将无法访问。....
作为经验法则:
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 |
+—————————————————+————————————+———————————+
____________________________________________________________________
| highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
\ xCanBeSeenBy | this | any class | this subclass | any
\__________ | class | in same | in another | class
\ | nonsubbed | package | package |
Modifier of x \ | | | |
————————————————*———————————————+———————————+———————————————+———————
public | ✔ | ✔ | ✔ | ✔
————————————————+———————————————+———————————+———————————————+———————
protected | ✔ | ✔ | ✔ | ✘
————————————————+———————————————+———————————+———————————————+———————
package-private | | | |
(no modifier) | ✔ | ✔ | ✘ | ✘
————————————————+———————————————+———————————+———————————————+———————
private | ✔ | ✘ | ✘ | ✘
____________________________________________________________________
推荐文章
- 在流中使用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