类和接口是Java程序设计语言的核心,它们也是Java语言的基本抽象单元。Java语言提供了许多强大的基本元素,供程序猿来设计类和接口。

要想区别一个设计良好的模块与一个设计不好的模块,最重要的因素是,这个模块对于外部其他模块而言,是否隐藏了内部的数据和其他的实现细节。一个设计良好的模块会隐藏所有的实现细节,把它的API与实现清晰的隔离开来。然后,模块之间只通过它们的API进行通信,一个模块不需要知道其他模块内部的工作情况,也就是所谓的封装。

封装之所以非常重要有许多理由,其中大多数理由都源于这样一个事实:它可以有效地解除一个系统中各模块之间的耦合关系,使得这些模块可以被独立地开发、测试、优化、使用、理解和修改。这样可以加速系统开发的速度,因为这些模块可以被并行地开发。它也减轻了维护的负担,因为程序员很快就可以理解这些模块,并且在调试它们的时候可以不伤害其他的模块。虽然封装本身无论是对内还是对外,都不会带来更好的性能,但是它使得有效的性能调节成为可能。一旦一个系统已经完成,通过分析就可以知道哪些模块影响了系统的性能,那么这些模块可以被进一步优化,而不会影响到其他模块的正确性。封装可以提高软件的可重用性,因为单独的模块并不依赖于其他的模块,除了开发这些模块所使用的环境之外,它们在其他环境中往往是有用。最后,封装也降低了构建大型系统的风险;即使整个系统并不成功,这些独立模块也有可能是成功的。

Java程序设计语言提供了许多设施来帮助坐到信息隐藏。其中一个设施是访问控制机制,它决定了类、接口和成员的可访问性。

一个实体的可访问性是由该实体声明所在的位置,以及该实体声明中所出现的访问修饰符公同决定的。正确地使用这些修饰符对于实现封装是非常关键的。

经验表明,你应该尽可能地使每一个类或成员不被外界访问。换句话说,你应该使用时最低可能的、并且与该软件的正确功能相一致的访问级别。

对于顶层的类和接口,它们只有两种可能的访问级别:包级私有的和公有的。如果你声明了一个具有public修饰符的顶层类或者接口,那么它是公有的;否则,它将是包级私有的。如果一个类或者接口能被做成包级私有的,那么它就应该被做成包级私有的。通过把一个类或接口做成包级私有的,它实际上成了这个包的实现的一部分,而不是该包导出API的一部分;并且,在以后的发行版本中,你可以对它进行修改、替换,或者去除,而无需担心会伤害到现有的客户。如果你把它做成公有的,你就有义务永远支持它,以保持兼容性。

如果一个包级私有的顶层类或接口只是在某一个类的内部被用到,那么你应该考虑使它成为后者的一个私有嵌套类。这样可以进一步降低它的可访问性,然而,这样做不像”使一个不必要的共公有类成为包级私有的类”那样重要,因为一个包级私有的类已经是这个包的实现的一部分,而不是其API的一部分。

对于成员有四种可能访问级别,下面按照可访问性递增的顺序列出来:

  • 私有的——只有在声明该成员的顶层类内部才可以访问这个成员

  • 包级私有的——声明该成员的包内部的任何类都可以访问这个成员。在技术上,它被称为”默认访问级别”,如果没有为成员指定访问修饰符的话,那么它就具有这样的访问级别。

  • 受保护的——该成员声明所在类的子类可以访问这个成员,并且,该成员声明所在的包内部的任何类也可以访问这个成员。

  • 公有的——任何地方都可以访问该成员。
    当你仔细地设计了一个类的公有API之后,接下去应该把所有其他的成员都变成私有的。只有当同一个包内的另一个类真正需要访问一个成员的时候,你才应该去掉private修饰符,使该成员变成包级私有的。如果你发现自己经常要做这样的事情,那么你应该重新检查你的系统设计,看看是否另一种分解方案所得到的类具有更好的分离特性,彼此之间耦合度更小。可以这样说,私有成员和包级私有成员都是一个类实现中的一部分,并不会影响到其导出的API。然而,如果这些域所在类是实现了Serializable接口,那么这些域可能会被”泄露”其导出的API中。

对于公有类的成员,当访问级别从包级私有变成保护级别时,会出现可访问性的巨大增加。受保护成员是一个类导出API的一部分,必须永远被支持。更进一步,一个导出的类的每一个受保护成员代表了该类对于一个实现细节的公开承诺。受保护的成员应该尽量少用。

有一条规则使得你无法降低一个方法的可访问性。如果一个方法改写了超类中的一个方法,那么子类中该方法的访问级别低于超类中的访问级别时不允许的。这样可以确保子类实例可以被用在任何可使用超类的实例的场合。如果你违反了这条规则,那么当你试图编译该子类的时候,编译器会产生一条错误信息。这条规则的一种特殊情形是,如果一个类实现了一个接口,那么接口中所有的方法在这个类中都必须被声明为公有的。这是因为接口中所有方法都隐含着公有访问级别。

公有类应该尽可能地包含公有的域。如果一个域是非final的,或者是一个指向可变对象的final引用,那么你一旦使它成为公有的,就放弃了对存储在这个域中的值进行限制的能力;当这个域被修改的时候,你也失去了采取任何行动的能力。一个简单的后果是,包含公有可变域的类不是线程安全地的。即使一个域是final的,并没有指向任何一个可变对象,那么,一旦你把这个域变成公有的,也就放弃了“切换到一个新的内部数据表示”的灵活性。

对于“公有类不应该包含公有域”这条规则也有一个例外,通过公有的静态final域来暴露类的常量是允许的。按照惯例,这样域的名字由大写字母组成,单词之间用下划线隔开。很重要的一点是,这些域要么包含原语类型的值,要么包含指向非可变对象的引用。如果一个final域包含一个指向可变对象的引用,那么它具有非final域的所有缺点。虽然引用本身不能被修改,但是它引用的对象可以被修改——这会导致灾难性的后果。

注意,非零长度的数组总是可变的,所以,具有公有的静态final数组域几乎总是错误的。如果一个类包含这样的一个域,客户将能够修改数组中的内容。这是安全漏洞中的一个常见根源:

public static final Type[] VALUES = {...};
private static final Type[] PRIVATE_VALUES ={...};
public static final List VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

另一种办法是,如果你要求编译时的类型的安全性,并且愿意损失一点性能的话,你可以把公有的数组替换成一个公有的办法,它返回私有数组的一份拷贝:

private static final Type [] PRIVATE_VALUES = {...};
public static final Type [] values(){
return (Type[])PRIVATE_VALUES.clone();
}

总之,你应该总会可能地降低可访问性,再仔细设计了一个最小的公有API之后,应该防止把任何杂散的类、接口和成员变成API的一部分。除了公有静态final域的特殊情形之外,公有类不应该包含公有域。并且确保公有静态final域所引用对象是不可变的。

转载于:https://www.cnblogs.com/ainima/p/6331825.html

Java性能优化(12):最小化类和成员可访问能力相关推荐

  1. Java性能优化(3):通过私有构造函数强化不可实例化的能力

    有时候你可能会编写出只包含静态方法和静态域的类,这样的类有一些很不好的名声,因为有些人在面向对象的语言中滥用这样的类来编写过程化的程序.尽管如此,它们也确实有它们特有的用处,我们可以利用这种类,把操作 ...

  2. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  3. 拉勾教育 | Java 性能优化实战 21 讲

    开篇词 开篇词 | Java 性能优化,是进阶高级架构师的炼金石 你好,我是李国.作为<Java 性能优化与面试 21 讲>这个课程的作者,我先来简单介绍下自己. 我曾任京东金融.陌陌科技 ...

  4. Java性能优化权威指南--笔记

    出处:http://xiongpq.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利. 原文 ...

  5. Java性能优化指南(一)

    2015年在大物流项目中,给项目团队做了几次Java性能优化和问题排查的分享,不过效果都不是很好.一直觉得偏向技术实践类的东西,单纯的听和单纯的讲收获都很有限,最好的做法是阅读学习-理解-实践-总结, ...

  6. Java性能优化技巧

    Java性能优化技巧 参考了些书籍,网络资源整理出来,适合于大多数Java应用 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序 ...

  7. java性能优化权威指南_Java性能优化权威指南 PDF扫描[132MB]

    Java性能优化权威指南主要为Java SE 和Java EE 应用的性能调优提供建议.主要包括以下几方面:性能监控.性能分析.Java HotSpot VM 调优.高效的基准测试以及Java EE ...

  8. java性能优化方案_Java性能优化要点

    Java性能优化要点 本文介绍如何通过以下几点从Java中挤压出性能,该大部分经验来自于Netty作者. JITJava即时编译器 当Java执行runtime环境时,每遇到一个新的类,JIT编译器在 ...

  9. Java 性能优化的七个方向

    了解了优化目标后,那接下来应该从哪些方面入手呢?本文主要侧重于理论分析,我们从整体上看一下 Java 性能优化都有哪些可以遵循的规律.本文主讲理论.关于实践,后续的文章会用较多的案例来细化本文的知识点 ...

最新文章

  1. VC中使用Matlab Engine出现无法找到libeng.dll的问题
  2. easyUI的目录结构
  3. 《Cassandra实战》CassSeller程序源代码下载
  4. ICLR 2020 | 可提速3000倍的全新信息匹配架构(附代码复现)
  5. 双端队列 BFS + Chamber of Secrets CodeForces - 173B
  6. Mac(OS X)安装、配置并使用MySQL数据库
  7. python经典100例(41-60)
  8. java子类怎么编译_java – 无法编译从基类实现抽象方法的子类
  9. CNN实操记录(goal:一日一更新)
  10. linux c++ 函数效率,Linux C++程序进行性能分析工具gprof使用入门
  11. VLFeat工具包在matlab使用方法
  12. 【多任务学习】多任务学习中的任务选择机制(Task Selection Policies for Multitask Learning)
  13. mac回车键、空格键失灵解决方法
  14. Vue框架学习笔记一
  15. elementui不生效
  16. tomcat启动报错:apache-tomcat-6.0.45/webapps/manager does not exist or is not a readable directory
  17. 电脑连接手机热点时,电脑能够搜到但是却连接不上的问题
  18. P3488 [POI2009]LYZ-Ice Skates
  19. 笔记本的网络出现红叉,网络连接不上,网络不可用
  20. 编辑时英文出现大间隔

热门文章

  1. Dynamics CRM中跨域调用Web API 2
  2. 062_判断用户输入的是 Yes 或 NO
  3. Spring Boot实战pdf
  4. 当你再面对大多数需求时能够说这些问题我以前做过,那你就。。。
  5. SonarQube代码质量管理工具安装与使用(sonarqube5.1.2 + sonar-runner-dist-2.4 + MySQL5.x)
  6. 2017 《Java技术预备作业》
  7. Jquery操作下拉列表和复选框,自定义下拉
  8. 软件常见基础问题总结
  9. 未来软件是什么样呢?数据库篇(转载)
  10. 《从0到1学习Flink》—— Flink 读取 Kafka 数据批量写入到 MySQL