在Java中,在创建类和接口以及处理继承时,是否有明确的规则来确定何时使用每个访问修饰符,即默认的(包私有)、公共的、受保护的和私有的?


当前回答

Public Protected Default和private是访问修饰符。

它们用于封装,或隐藏和显示类的内容。

类可以是公共的或默认的类成员可以是公共的、受保护的、默认的或私有的。

课堂外无法访问私人课程默认值只能在包中访问。在包以及扩展它的任何类中受到保护。公众对所有人开放。

通常,成员变量被定义为私有的,但成员方法是公共的。

其他回答

(注意:我不是一个Java程序员,我是一个Perl程序员。Perl没有正式的保护措施,这也许就是为什么我如此理解这个问题的原因:)

私有的

就像你想的那样,只有声明它的类才能看到它。

包专用

它只能由声明它的包看到和使用。这是Java中的默认设置(有些人认为这是错误的)。

受保护的

包Private+可以由子类或包成员看到。

平民的

每个人都能看到。

出版

在我控制的代码之外可见。(虽然不是Java语法,但这对本次讨论很重要)。

C++定义了一个称为“朋友”的附加级别,你对它了解得越少越好。

你什么时候应该用什么?整个想法是封装以隐藏信息。您希望尽可能地向用户隐藏某些操作的细节。为什么?因为这样你以后就可以更改它们,而不会破坏任何人的代码。这使您可以优化、重构、重新设计和修复错误,而不用担心有人在使用您刚刚大修过的代码。

因此,经验法则是让事物尽可能地可见。从私密开始,只在需要时增加更多的可见性。只公开用户需要知道的信息,你公开的每一个细节都限制了你重新设计系统的能力。

如果您希望用户能够自定义行为,而不是将内部公开以便他们可以覆盖它们,那么通常最好将这些内容插入到对象中并将接口公开。这样他们就可以简单地插入一个新对象。例如,如果您正在编写一个CD播放器,并希望“go find info about this CD”位可定制,而不是将这些方法公开,那么您应该将所有这些功能放入其对象中,并仅将对象getter/setter公开。通过这种方式,吝啬于暴露自己的内心会鼓励良好的组合和关注的分离

我只坚持“私人”和“公共”。许多OO语言都有这一点。“受保护”可能很方便,但这是一个骗局。一旦一个接口超过了私有,它就超出了你的控制范围,你必须去查看其他人的代码才能找到用途。

这就是“发布”的概念所在。更改接口(重构它)需要找到使用它的所有代码并进行更改。如果接口是私有的,那么没问题。如果它受到保护,你必须找到所有的子类。如果它是公开的,你必须找到使用你的代码的所有代码。有时这是可能的,例如,如果您正在编写仅供内部使用的公司代码,那么接口是否公开无关紧要。您可以从公司存储库中获取所有代码。但是,如果一个接口被“发布”,如果有代码在您的控制之外使用它,那么您将被罚款。您必须支持该接口,否则可能会破坏代码。即使是受保护的接口也可以被认为是已发布的(这就是为什么我不关心受保护的)。

许多语言发现公共/受保护/私有的等级性质过于局限,不符合现实。为此,有一种特质类的概念,但这是另一种表现。

David的回答提供了每个访问修饰符的含义。至于何时使用每一个,我建议公开所有用于外部使用的类和每个类的方法(其API),并将其他所有内容私有化。

随着时间的推移,您将了解何时将某些类包设为私有,以及何时声明某些方法受保护以便在子类中使用。

这是该表的一个更好的版本,其中还包括一个模块列。


解释

私有成员(i)只能在声明的同一类中访问。没有访问修饰符(j)的成员只能在同一包中的类中访问。受保护的成员(k)可以在同一包中的所有类和其他包中的子类中访问。公共成员(l)对所有类都是可访问的(除非它驻留在不导出声明它的包的模块中)。


要选择哪个修饰符?

访问修饰符是一种帮助您防止意外破坏封装(*)的工具。问问自己,您是否希望成员是类、包、类层次结构的内部成员,或者根本不是内部成员,并相应地选择访问级别。

示例:

长字段internalCounter可能应该是私有的,因为它是可变的,并且是实现细节。只应在工厂类中实例化的类(在同一个包中)应具有包限制构造函数,因为不可能从包外部直接调用它。应保护在呈现之前调用并用作子类中钩子的内部void beforeRender()方法。从GUI代码调用的void saveGame(File dst)方法应该是公共的。

(*)封装到底是什么?

当你想到访问修饰符时,你可以这样想(适用于变量和方法):

public-->可从任何位置访问private-->只能在声明它的同一类中访问

现在,当涉及到默认和受保护时,就会出现混乱

默认-->不存在访问修饰符关键字。这意味着它严格在类的包中可用。在该包之外,任何地方都无法访问。

protected-->略低于默认值,并且除了相同的包类之外,它可以由声明的包之外的子类访问。

注:这只是对公认答案的补充。

这与Java访问修改器有关。

从Java访问修改器:

Java访问修饰符指定哪些类可以访问给定的类及其字段、构造函数和方法。访问修饰符可以为类、其构造函数、字段和方法。Java访问修饰符有时也在日常使用中使用语音作为Java访问说明符,但正确的名称是Java访问修改器。类、字段、构造函数和方法可以具有四种不同的Java访问修饰符:列表项目私有的默认(包)受保护的平民的

从控制对班级成员的访问教程:

访问级别修饰符确定其他类是否可以使用特定字段或调用特定方法。有两个级别访问控制:在顶层public或package private(没有显式修饰符)。在成员级别public、private、protected或package private(没有显式修饰符)。类可以用修饰符public声明,在这种情况下类对任何地方的所有类都可见。如果类没有修饰符(默认值,也称为包专用),它仅可见在其自己的包装内下表显示了每个成员允许的成员访问权限修改器。╔═════════════╦═══════╦═════════╦══════════╦═══════╗║ 修改器║ 班║ 包裹║ 子类║ 世界║╠═════════════╬═══════╬═════════╬══════════╬═══════╣║ 平民的║ Y║ Y║ Y║ Y║║ 受保护的║ Y║ Y║ Y║ N║║ 无修饰符║ Y║ Y║ N║ N║║ 私有的║ Y║ N║ N║ N║╚═════════════╩═══════╩═════════╩══════════╩═══════╝第一个数据列指示类本身是否有权访问由访问级别定义的成员。正如你所看到的,一个班级总是可以访问自己的成员。第二列指示是否类(无论其父母)有权访问该成员。第三列表示在该包外部声明的类的子类是否具有访问该成员。第四列指示是否所有类可以访问该成员。访问级别以两种方式影响您。首先,当您使用来自另一个源,访问级别决定您自己的这些类的哪些成员类可以使用。第二,当你写一门课时,你需要决定类中每个成员变量和每个方法的访问级别应该有。