在不破坏专门与此类公众一起工作的“外部代码”的情况下,从根本上改变整个班级内部(所有私人)的能力将像以前一样发挥作用。您可以从根本上改变微波的 ALL 内部实现——更换所有备件,插入其他板,但所有公共方法和参数将保持不变。从视觉上看,微波炉甚至不会发生变化——用户甚至不会猜到有什么变化,只是它在主观或客观上变得更好用了。
您自己的答案:有API(应用程序编程接口)这样的东西。从这个角度来看java-класса,他public-методы的就是他的API,tk 。通过这些方法java-классом,您可以在代码中与它交互。反过来,private-методы总是隐藏在外面。因此,修改private-методов不会影响签名public-методов。也就是说,所有与 this 的外部交互java-классом,在修改它之后private-методов,很可能不需要修改。这就是私有方法的优势!
区分一个设计良好的模块和一个糟糕的模块的最重要的因素是它的内部数据和其他实现细节对其他模块的隐藏程度。一个设计良好的模块通过明确地将其 API 与其实现分开来隐藏所有实现细节。模块仅通过它们的 API 相互通信,它们都不知道另一个模块内部正在进行什么处理。这个概念称为信息隐藏 ( information hiding) 或封装 ( encapsulatiori) ,是软件开发的基本原则之一。
在为您的类精心设计了一个公共 API 之后,您应该将该类的所有其他成员设为私有。并且只有当同一包中的另一个类确实需要访问某个成员时,您才可以删除修饰符private并使该成员在整个包中可用。如果您发现此类成员太多,请再次检查您的系统模型并尝试找到另一种方法对它们进行分类,这样它们之间会更好地相互隔离。如前所述,私有成员和仅包成员都是类实现的一部分,通常对其外部 API 没有影响。但是,如果该类实现了Serializable.
如果公共类成员的访问级别从打包更改为受保护,则该成员的可访问性会显着增加。对于此类,受保护成员是外部 API 的一部分,因此必须永久支持。此外,在包外传递的类中存在受保护成员表示实现细节的公开传输。使用受保护成员的需要相对较少。有一条规则限制了您降低方法可用性的能力。如果任何方法覆盖超类方法,则子类中的方法不允许具有比超类中的方法更低的访问级别。这是为了确保子类实例可以在任何地方使用,可以使用超类实例的地方。如果你违反了这条规则,那么当你试图编译这个子类时,编译器就会产生一条错误信息。该规则的一个特例:如果一个类实现了一个接口,那么这个接口中提供的所有类方法都必须声明为 public (public). 这是因为在接口中,所有方法都被隐式假定为公共的。
当编写足够大的代码(无论是类、函数还是其他任何东西)时,分解是一项重要的技术。您将功能划分为逻辑部分,并在主要功能中添加公共逻辑,就像从积木中一样。
同时,砖块本身可能不适合从外部进入。例如,一个公共方法可以检查输入参数,但是 brick helper 方法不再需要这个,因为它们只能从内部调用。如果这些方法是公共的,它们将需要实现参数检查,并且在实现它们时,不能期望它们在您控制的时间被调用。
此外,如果您知道调用它们的代码稍后会解决此问题,则内部方法有权扰乱类的状态。通过公开这些方法,该类的用户可以在不修复类的情况下扰乱类的内部状态。
那么,内部方法可能与类应该提供的内容及其外部接口无关。例如,如果一个类代表一辆汽车,那么其中将英寸转换为厘米的公共方法看起来很荒谬。但是里面很可能需要这样的翻译。
好吧,最后,公共方法是对用户的承诺。公共方法的每次更改(删除、签名更改,有时还添加)对客户来说都是重大更改,他们必须重新考虑您的类使用的代码。因此,您不应该在没有特殊需要的情况下只更改类的公共方法。但是私有方法的变化通常发生在批量重构过程中:方法被简化、组合、分解成几个,在层次结构中上下移动,它们的语义发生变化,所有这些都不会以任何方式影响您的类的用户。
要添加一些东西,始终可以安全地更改私有方法,因为您可以肯定地知道它只在其自己的类中被调用,没有外部类可以调用私有方法(他们甚至看不到它)。
因此,拥有私有方法总是好的,因为您知道更改它没有问题,即使您可以安全地向该方法添加额外的参数。
至于公共方法,任何人都可以调用这个方法,所以如果你添加/删除一个参数,你也需要改变对这个方法的所有调用。
以下是在 Java 中将变量或方法设为私有的一些优点:
私有方法被很好地封装在类中,开发人员知道它们不会在代码的其他任何地方使用,这使他们有信心在没有任何副作用的情况下更改、更改或改进私有方法。
如果你看一个私有方法,你可能知道没有人使用它,这在调试 java 程序时有很大帮助。
Netbeans、IDEA 和 Eclipse 等 IDE 使用此信息并自动检查类中是否使用了私有方法,并可以显示适当的警告以提高代码质量或删除未使用的语句、变量或方法。
私有方法在 Java 中使用静态绑定,它们在编译时绑定,这与在运行时发生的动态绑定相比很快,并且还为 JVM 提供了内联方法或优化方法的机会。
在 java 中使变量私有并为它们提供 getter 和 setter 使您的类与 Java bean 命名和其他基于反射的结构(如 displaytag)兼容。
一篇关于该主题的好文章(在我看来) 。
资料来源 - K. Horstmann、G. Cornell - Java 2. 基础知识。第 1 卷 - 威廉姆斯 (2014)(第 158 页)
总的来说,一切都简单得不切实际。比许多人在这里写的要容易得多:)
private 修饰符的出现是由于 OOP 的主要原则之一——封装。封装背后的主要思想是使尽可能多的方法/属性成为私有的。结果我们有:
总计:由于使用封装原则,程序员不太可能犯愚蠢的错误,并提高了中小型、中型和大型项目的性能。当类本身发生变化时,代码会变得更简单、更安全。
(在几个小班的非常小的项目上,程序员的生产力可能会因为“过度行动”而下降,但实际上,这仍然是值得的)
无关
如果有一种
private
方法——这已经是一种黑客攻击的邀请,即通过Java 反射 API调用私有方法——谷歌很容易,我什至不会举例说明它是如何完成的。在这种情况下,读起来很有趣:
现在到了问题的关键
有时会制作私有方法,以便在某天晚些时候公开它们。我个人通过 Android 中的 SMS/MMS API 观察到这一点,在早期版本的 Android 中,使用 SMS 的方法大多被隐藏 /
private
,然后在 KitKat 区域的某个地方开始打开(声明public
)并大声宣布新的API :)因此,除了封装之外,我还看到了使用私有方法作为规划未来版本的一种方式的优势。
private-модификатор
- 它是数据封装的一部分。API
(应用程序编程接口)这样的东西。从这个角度来看java-класса
,他public-методы
的就是他的API
,tk 。通过这些方法java-классом
,您可以在代码中与它交互。反过来,private-методы
总是隐藏在外面。因此,修改private-методов
不会影响签名public-методов
。也就是说,所有与 this 的外部交互java-классом
,在修改它之后private-методов
,很可能不需要修改。这就是私有方法的优势!有封装这样的东西。
也就是说,你的类的用户不应该知道你的类的内部结构。
用户必须通过不允许错误分配的特殊方法与字段交互。
我会总结答案
private 修饰符是数据封装的一部分。
不能在类外的代码中直接设置私有类成员。但与此同时,您可以完全控制数据在对象中的使用方式和时间。因此,一个正确实现的类形成了一种可以使用的“黑盒子”,但其动作的内部机制“对外界干扰是封闭的”。
结果我们有:
1 更简单的代码结构(可以准确看出实现对内重要的地方,对外部对象重要的地方)
1.1 当编写足够大的代码(无论是类、函数还是其他任何东西)时,分解是一项重要的技术。您将功能划分为逻辑部分,并在主要功能中添加公共逻辑,就像从积木中一样。
同时,砖块本身可能不适合从外部进入。例如,一个公共方法可以检查输入参数,但是 brick helper 方法不再需要这个,因为它们只能从内部调用。如果这些方法是公共的,它们将需要实现参数检查,并且在实现它们时,不能期望它们在您控制的时间被调用。
2 此外,内部方法有权破坏类的状态,如果你知道调用它们的代码稍后会解决这个问题的话。通过公开这些方法,此类的用户可以在不修复类的情况下扰乱类的内部状态。
3 安全密码
3.1 不可能错误地调用另一个类不应该调用的方法。
3.2 一个不需要从外部改变的属性是不可能从外部改变的。
4 能够在不破坏“外部代码”的情况下更改类内部结构的实现(与私有相关的所有内容),而“外部代码”专门与公共相关联。
4.1. 在协作项目中,程序员由于不了解外部代码的特性而犯错误的机会较少。
4.2 提高中小型、中型和大型项目的生产率。代码变得更简单、更安全。(在几个小班的非常小的项目上,程序员的生产力可能会因为“过度行动”而下降,但实际上,这仍然是值得的)
4.3 最后,公共方法是对用户的承诺。公共方法的每次更改(删除、签名更改,有时还添加)对客户来说都是重大更改,他们必须重新考虑您的类使用的代码。因此,您不应该在没有特殊需要的情况下只更改类的公共方法。但是私有方法的变化通常发生在批量重构过程中:方法被简化、组合、分解成几个,在层次结构中上下移动,它们的语义发生变化,所有这些都不会以任何方式影响您的类的用户。
5 私有方法在 Java 中使用静态绑定,它们在编译时绑定,这与运行时发生的动态绑定相比很快,并且还为 JVM 提供了内联方法或优化方法的机会。
6 在 java 中使变量私有并为它们提供 getter 和 setter 使您的类与 Java bean 命名和其他基于反射的结构(如 displaytag)兼容。
7 如果你看一个私有方法,你可能知道没有人使用它,这在调试java程序时有很大帮助。
8 更方便的提示(当你输入一个句号时,系统会提示你选择一个方法/参数)——IDE 在使用一个类时不会显示任何“额外的”(只有公共的)。
Netbeans、IDEA 和 Eclipse 等 IDE 使用此信息并自动检查类中是否使用了私有方法,并可以显示适当的警告以提高代码质量或删除未使用的语句、变量或方法。
区分一个设计良好的模块和一个糟糕的模块的最重要的因素是它的内部数据和其他实现细节对其他模块的隐藏程度。一个设计良好的模块通过明确地将其 API 与其实现分开来隐藏所有实现细节。模块仅通过它们的 API 相互通信,它们都不知道另一个模块内部正在进行什么处理。这个概念称为信息隐藏 (
information hiding
) 或封装 (encapsulatiori
) ,是软件开发的基本原则之一。信息隐藏之所以重要有很多原因,其中大部分是由于这种机制有效地将组成系统的模块彼此隔离开来,使它们可以单独开发、测试、优化、使用、研究和更新。这加快了系统的开发,因为可以并行创建不同的模块。此外,应用程序维护的成本也降低了,因为每个模块都可以快速检查和调试,而损害其他模块的风险最小。隐藏信息本身不能提供良好的绩效,但它为有效的绩效管理创造了条件。当系统开发完成并且分析程序显示哪些模块导致性能下降时,您可以在不影响其他模块功能的情况下对其进行优化。信息隐藏增加了程序的可重用性,因为每个单独的模块都独立于其他模块,并且通常在与设计它的环境不同的环境中有用。最后,隐藏信息降低了构建大型系统的风险:即使整个系统不成功,单个模块也可能成功。
java 编程语言有很多隐藏信息的可能性。其中之一是访问控制机制(
access control
),它规定了accessibility
接口、类和类成员的可访问性程度( )。任何实体的可访问性取决于它的声明位置以及它的声明中存在的访问修饰符(如果有的话)(private
,protected
或public
)。正确使用这些修饰符对隐藏信息大有帮助。主要规则是您应该使每个类或成员尽可能不可访问。换句话说,您应该使用尽可能低的访问级别,但仍允许您正在创建的程序正常运行。
对于顶级(非嵌套)类和接口,只有两种可能的访问级别:仅限包 (
package-private
) 和公共 (public
)。如果您要使用修饰符声明顶级类或接口public
,它将是公开的,否则它将只在包内可用。如果顶级类或接口只能在包中可用,那就这样吧。这使得类或接口成为包实现的一部分,而不是其外部 API 的一部分。您可以对其进行修改、更换或将其从包装中移除,而不必担心伤害您的客户。如果您公开类或接口,则您有责任始终维护它以保持兼容性。如果仅在包内可用的顶级类或接口仅在一个类中使用,则应考虑将其设置为嵌套在使用它的类中的私有类(或接口)。因此,您将进一步降低其可用性。对于类成员(字段、方法、嵌套类和嵌套接口),有四种可能的访问级别,此处按可访问性递增的顺序列出:
Private (
private
) - 该成员只能在声明它的顶级类中访问。仅在包内可用(包私有)- 成员可从声明它的包内的任何类访问。形式上,此级别称为默认访问权限,这是您在未指定访问修饰符的情况下获得的访问级别。
Protected (
protected
) - 该成员可用于声明该成员的类的子类(具有较小的限制);可以从已声明该成员的包中的任何类访问该成员。打开 (
public
) - 可以从任何地方访问该成员。在为您的类精心设计了一个公共 API 之后,您应该将该类的所有其他成员设为私有。并且只有当同一包中的另一个类确实需要访问某个成员时,您才可以删除修饰符
private
并使该成员在整个包中可用。如果您发现此类成员太多,请再次检查您的系统模型并尝试找到另一种方法对它们进行分类,这样它们之间会更好地相互隔离。如前所述,私有成员和仅包成员都是类实现的一部分,通常对其外部 API 没有影响。但是,如果该类实现了Serializable
.如果公共类成员的访问级别从打包更改为受保护,则该成员的可访问性会显着增加。对于此类,受保护成员是外部 API 的一部分,因此必须永久支持。此外,在包外传递的类中存在受保护成员表示实现细节的公开传输。使用受保护成员的需要相对较少。有一条规则限制了您降低方法可用性的能力。如果任何方法覆盖超类方法,则子类中的方法不允许具有比超类中的方法更低的访问级别。这是为了确保子类实例可以在任何地方使用,可以使用超类实例的地方。如果你违反了这条规则,那么当你试图编译这个子类时,编译器就会产生一条错误信息。该规则的一个特例:如果一个类实现了一个接口,那么这个接口中提供的所有类方法都必须声明为 public (
public
). 这是因为在接口中,所有方法都被隐式假定为公共的。公共类中的公共字段(相对于公共方法)应该很少见(如果它们应该出现的话)。如果一个字段不是最终的,或者如果它有一个修饰符并引用一个可变对象,那么通过将它公开你就错过了对可以写入该字段的值施加限制的机会。您也不再能够采取任何行动来响应对此字段的更改。由此得出的简单结论是,具有公共可变字段的类在具有多线程的系统中不是线程安全的。即使字段具有修饰符
final
并且不引用可变对象,通过将其声明为公共,您也放弃了灵活过渡到没有该字段的新内部数据表示的能力。禁止公共类具有公共字段的规则有一个例外。使用字段,
public static final
类可以在外部公开常量。按照惯例,此类字段的名称由大写字母组成,名称中的单词由下划线分隔。这些字段必须包含简单值或对不可变对象的引用。具有final
包含对可变对象的引用的修饰符的字段具有没有修饰符的字段的所有缺点final
:虽然引用本身不能更改,但它指向的对象可以更改 - 具有致命的后果。请注意,非零长度的数组始终是可变的。因此,几乎不可能将数组字段声明为
public static final
. 如果该类有这样的字段,客户将能够更改该数组的内容。这通常是安全系统中出现漏洞的原因。开放数组应该替换为封闭数组和开放不可变列表:
或者,如果您需要在编译时进行类型检查并且愿意牺牲性能,您可以将公共数组字段替换为返回私有数组副本的公共方法。
让我们总结一下。您应该始终尽可能降低访问级别。通过仔细设计最小的公共 API,您必须防止任何随机类、接口和成员成为该 API 的一部分。除了 type 的字段外
public static final
,公共类中不应有其他公共字段。确保类型字段中引用的对象public static final
不可变。资料来源:“Java。有效的编程。” 约书亚·布洛赫。
OOP 的首要原则是封装。事实上,这意味着能够向使用该语言的对象的用户隐藏非必要的实现细节。对象的用户欢迎封装,因为这种 OOP 原则简化了编程任务。无需担心在幕后完成类工作的多行代码。您所需要做的就是创建一个实例并发送适当的消息。
封装的一方面是数据保护。理想情况下,对象状态数据应该定义为私有的。在这种情况下,“外界”将被迫“低声请求”更改或读取相应值的权利。(c) 特罗尔森