在Java中,是否有明确规定何时使用每个访问修饰符,即默认值(包私有), public
, protected
和 private
制作时 class
和 interface
处理继承?
在Java中,是否有明确规定何时使用每个访问修饰符,即默认值(包私有), public
, protected
和 private
制作时 class
和 interface
处理继承?
官方教程 可能对你有用。
│班级│包装│子类│子类│世界 │││(相同的pkg)│(diff pkg)│ ────────────┼───────┼─────────┼──────────┼──────── ──┼──────── 公开│+│+│+│+│+ ────────────┼───────┼─────────┼──────────┼──────── ──┼──────── 受保护的│+│+│+│+│ ────────────┼───────┼─────────┼──────────┼──────── ──┼──────── 没有修饰符│+│+│+││ ────────────┼───────┼─────────┼──────────┼──────── ──┼──────── 私人│+││││ +:可访问 空白:无法访问
(警告:我不是Java程序员,我是Perl程序员.Perl没有正式的保护,这也许是我理解这个问题的原因:))
就像你想的那样,只有 类 声明它可以看到它。
只能被看到和使用 包 在其中宣布。这是Java中的默认值(有些人认为是错误的)。
Package Private +可以通过子类或包成员看到。
每个人都可以看到它。
在我控制的代码外面可见。 (虽然不是Java语法,但对于此讨论非常重要)。
C ++定义了一个名为“friend”的附加级别,你知道的越少越好。
你什么时候应该用什么?整个想法是隐藏信息的封装。您希望尽可能隐藏用户完成某些操作的详细信息。为什么?因为那样你可以在以后更改它们而不会破坏任何人的代码。这使您可以优化,重构,重新设计和修复错误,而无需担心有人正在使用您刚刚彻底检查过的代码。
因此,经验法则是使事物只能像它们必须一样可见。从私有开始,只根据需要添加更多可见性。只公开那些对用户来说绝对必要的信息,你公开的每一个细节都会让你重新设计系统。
如果您希望用户能够自定义行为,而不是将内部公开,以便他们可以覆盖它们,那么将这些内容推入对象并使该接口公开通常是一个更好的主意。这样他们就可以简单地插入一个新对象。例如,如果您正在编写CD播放器并希望“查找有关此CD的信息”位可自定义,而不是将这些方法公开,您可以将所有功能放入其自己的对象中并使公共getter / setter成为公共对象。以这种方式吝啬暴露你的胆量鼓励良好的成分和关注点的分离
就个人而言,我坚持只是“私人”和“公共”。许多OO语言就是这样。 “受保护”可以派上用场,但这真的是一种骗局。一旦界面不仅仅是私人的,它就在你的控制之外,你必须去寻找其他人的代码才能找到用途。
这就是“已发布”的概念所在。更改界面(重构它)需要您找到使用它的所有代码并进行更改。如果界面是私有的,那么没问题。如果它受到保护,你必须找到你所有的子类。如果它是公开的,你必须找到使用你的代码的所有代码。有时这是可能的,例如,如果您正在处理仅供内部使用的公司代码,那么如果接口是公共的则无关紧要。您可以从公司存储库中获取所有代码。但是如果一个界面被“发布”,如果有代码在你的控制范围之外使用它,那么你就被软管了。您必须支持该接口或冒险破坏代码。甚至受保护的接口也可以被认为是已发布的(这就是我不打扰受保护的原因)。
许多语言发现公共/受保护/私有的等级性质太过限制而不符合现实。为此,有一个概念 特质班,但这是另一个节目。
这是表格的更好版本。 (模块专栏的未来证明。)
一个 私人的 成员是 只要 可以在声明的同一类中访问。
有会员 没有访问修饰符 只能在同一个包中的类中访问。
一个 保护 成员可以在同一个包中的所有类中访问 和 在其他包的子类中。
一个 上市 所有类都可以访问成员(除非它位于 模 不导出它声明的包)。
访问修饰符是一种帮助您防止意外破坏封装的工具(*)。问问自己,您是否希望该成员成为类,包,类层次结构内部的内容,或者根本不是内部成员,并相应地选择访问级别。
例子:
long internalCounter
应该是私有的,因为它是可变的和实现细节。void beforeRender()
在渲染之前调用的方法以及在子类中用作钩子的方法应该受到保护。void saveGame(File dst)
从GUI代码调用的方法应该是公共的。(*) 什么是封装?
| 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 | | ✘ | ✘ | ✘
简单的规则。首先声明一切都是私密的。然后随着需求的出现向公众发展,设计需要保证。
当暴露成员时,问问自己是否暴露了表示选择或抽象选择。第一个是你想要避免的东西,因为它会在实际表示中引入太多依赖,而不是它的可观察行为。
作为一般规则,我尝试通过子类化来避免重写方法实现;搞砸逻辑太容易了。如果要覆盖它,则声明抽象受保护的方法。
此外,在重写时使用@Override注释可以防止重构时出现问题。
它实际上比简单的网格显示要复杂一些。网格告诉您是否允许访问,但是访问的确切构成是什么?此外,访问级别以复杂的方式与嵌套类和继承交互。
还调用“默认”访问(由缺少关键字指定) 包私有。例外:在界面中,没有修饰符意味着公共访问;禁止公开以外的修饰语。枚举常量总是公开的。
是否允许访问具有此访问说明符的成员?
private
:仅当成员与调用代码在同一个类中定义时。protected
:相同的包,或者如果成员是在包含调用代码的类的超类中定义的。public
:是的。局部变量和形式参数不能使用访问说明符。由于根据范围规则它们本身就无法进入外部,因此它们实际上是私密的。
仅适用于顶级作用域中的类 public
允许包和私有。这种设计选择大概是因为 protected
和 private
在包级别是多余的(没有包的继承)。
所有访问说明符都可以在类成员(构造函数,方法和静态成员函数,嵌套类)上使用。
有关: Java类可访问性
访问说明符可以严格排序
public> protected> package-private> private
意思是 public
提供最多的访问, private
至少。私有成员可能的任何引用也对包私有成员有效;对包私有成员的任何引用在受保护的成员上都是有效的,依此类推。 (允许访问受保护的成员到同一个包中的其他类被认为是一个错误。)
private[this]
。)你还必须考虑 嵌套 范围,例如内部类。复杂性的一个例子是内部类具有成员,它们本身可以使用访问修饰符。所以你可以拥有一个公共成员的私人内部阶级;会员可以访问吗? (见下文。)一般规则是查看范围并递归思考,看看是否可以访问每个级别。
但是,这非常复杂,而且详情如下, 参考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
一些相关问题:
根据经验:
因此,如果我们将访问权限分为三个权限:
然后我们有这个简单的表:
+—-———————————————+————————————+———————————+
| | Same | Different |
| | Package | Packages |
+—————————————————+————————————+———————————+
| private | D | |
+—————————————————+————————————+———————————+
| package-private | | |
| (no modifier) | D R I | |
+—————————————————+————————————+———————————+
| protected | D R I | I |
+—————————————————+————————————+———————————+
| public | D R I | R I |
+—————————————————+————————————+———————————+
很短的
public
:无处不在。 protected
:可以通过相同包的类和驻留在任何包中的子类访问。private
:只能在同一个类中访问。