`
TonyLian
  • 浏览: 395865 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【第12条】使类和成员的可访问能力最小化

阅读更多

《第4章 类和接口》

 

    类和接口是Java语言的核心,本章包含的一些指导原则,可以帮助你更好地设计出更加有用、健壮、灵活的类和接口。

 

【第12条】使类和成员的可访问能力最小化

 

    要想区别一个设计良好的模块与一个设计不好的模块,最重要的因素是,这个模块对于外部的其它模块而言,是否隐藏了内部的数据和其他的实现细节。换句话说,就是模块的设计者是否对其进行了良好的封装

 

    经验表明,你应该尽可能地使每一个类或成员不被外界访问。也就是说,在保证与该模块相关的程序能够正确运行的前提下,尽可能使用最低可能的访问级别。那些一上来不加思索就统统 public 的做法显然是要着重声讨的。

 

    对于顶层的(非嵌套的)类和接口,它们只有2种访问级别:包级私有(package-private)公有(public)。如果选择了包级私有,那么它只是这个包的实现的一部分,而不是该包对外提供服务的API的一部分。在以后的版本中,你可以对它进行修改、替换甚至删除,而无需担心会伤害到现有的使用者。而如果选择的公有的,你就有义务永远支持它,以保持兼容性。

   

    对于成员(域和方法),访问级别共为4种:

 ● 私有的(private)——只有该成员的顶层类中才能访问

 ● 包级私有(package-private)——本包内任何类都可访问

 ● 保护的(protected)——本包内的任何类和所在类的子类都可以访问

 ● 公有的(public)——任何地方都可以访问

 

    私有、保护、公有 是几乎所有人都知道的,但是包级私有取不敢这么说。再有一点就是保护的,一来说“所在类的子类都可以访问”是尽人皆知的,但和包级私有一样“本包内任何类都可访问”这一点同样不敢说是尽人皆知。

 

   也正是这个“包级私有”得以让我们既可以按功能分解为不同的类,又可以不对外部开发访问权限。其实就我个人来说,如果能有一个“反import”,用以写明只对谁谁谁可访问才好呢,这样就不必把这样的一些类都拘泥于同一个包内了。

 

   那么“包级私有”的修饰符是什么呢?其实什么都不写就是包级私有,如:

class PackagePrivateClass {

     String name;
.....

}

 

 

    看到这样的代码,如果是来自“高手”的,你大可不必去担心“这家伙是不是偷懒,或者疏忽漏掉了修饰符?”。但是,如果这段代码是来自“基层”的,我还是建议你最好多问个问什么。

 

    最后,有一个小知识,或者叫小结论:具有公有的静态final数组域几乎总是错误的。注意这句话共有4个定语——公有的、静态的、final的、数组。

// 这可以肯定是错误的
public static final Type[] VALUES = { ... };  


// 应该改成这样
private static final Type[] PRIVATE_VALUES = { ... };  

public static final List VALUE = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));


 
 
// 或者这样写(可能损失一点性能),前提是Type实现了克隆接口,而且你不反感克隆
private static final Type[] PRIVATE_VALUES = { ... };  

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


 

 总结一下,你应该总是尽量降低可访问性,否则你就有义务对你开放出去的东西负责到底。

 

   看完这一条,我要做的是,重新审视一下我的 xxxx.util.support 包,这个包中的类都是用来对 util 里的类做支持的(幕后英雄)。根据本条的“精神”,我取消了 util.support包,转而把这些支持类都放入 util 包里,做成了包级私有类,这样这些support类就仅仅对util中的类负责了,在外部就看不到它们了,我就没有义务使它们永远保持兼容了。

 

    另外,还有一点就是在util包中找到那些仅仅是为Framework中某些类服务的工具类,这些类的设计目的就不是给Framework的使用者用的,所以同样地把它们转移到被调用者的包里,做成包级私有(好在没有同时对两个及以上包提供服务的util类)。util包中只保留那些目的是给外部使用者服务的类。

 

 

【Effective Java 学习笔记】系列连载专题请见:
http://tonylian.iteye.com/categories/64208

 

分享到:
评论

相关推荐

    重构36计.docx

    第十二计:循环中早用continue减少条件嵌套 8 第十三计:为集合类型的成员变量提供增删改查函数 8 第十四计:避免一个临时变量充当多种角色 9 第十五计:引入NULL Object来避免大量的对象合法性判断 10 第十六计:...

    C++入门到精通

    第 7章到第12 章 第三篇 集中在 C++为基于过程化的程序设计所提供的支持上 第 7 章介绍C++函数机制 函数封装了一组操作 它们通常形成一项单一的任务 如 print() 名 字后面的括号表明它是一个函数 关于程序域和...

    Java开发技术大全(500个源代码).

    otherClass.java 从类的外部访问对象的成员 showInstVar.java 演示不同的对象拥有不同的成员变量 showMain.java 演示main方法访问本类成员 showMethod.java 演示如何定义一个方法体 showReturn_1.java return...

    Effective.C++.中文第二版.50条款doc文档.chm

    条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同 条款14: 确定基类有虚析构函数 条款15: 让operator=返回*this的引用 条款16: 在operator=中对所有数据成员赋值 条款17: 在operator=中检查给自己赋值...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    第8章 类和对象 8.1 面向对象程序设计方法概述 8.1.1 什么是面向对象的程序设计 8.1.2 面向对象程序设计的特点 8.1.3 类和对象的作用 8.1.4 面向对象的软件开发 8.2 类的声明和对象的定义 8.2.1 类和对象的关系 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    第8章 类和对象 8.1 面向对象程序设计方法概述 8.1.1 什么是面向对象的程序设计 8.1.2 面向对象程序设计的特点 8.1.3 类和对象的作用 8.1.4 面向对象的软件开发 8.2 类的声明和对象的定义 8.2.1 类和对象的关系 ...

    Java开发技术大全 电子版

    第12章类型包装器、自动装箱和元数据(注释)372 12.1类型包装器372 12.1.1字符类型包装器372 12.1.2布尔类型包装器373 12.1.3数字类型包装器373 12.2自动装/拆箱375 12.2.1自动装箱与方法375 12.2.2表达式中...

    软件工程与软件测试自动化教程

    第12章 软件自动测试和测试用例生成(OO-Test) 12. 1 激活Panorama/Test 12. 2 测试用例的生成 12. 2. 1 为动态分析程序准备和运行测试用例 12. 2. 2 加载测试用例 12. 2. 3 创建测试用例 12. 2. 4 运行测试...

    精易官方免费模块v3.60版

    4.删除“内存_优化” 在程序最小化和后台时系统会自动调用该函数来节省内存 个人使用,容易出现各种各样的问题,详情:http://bbs.125.la/thread-13690978-1-1.html 感谢 红河 的提醒 ,感谢 落雪 的详细分析文章 ...

    java 面试题 总结

    派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 3.封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即...

    Windows窗口自动化操作类forVB6_V1.7纯净版 源码

    ' V1.5 增加了窗口最大最小化,隐藏显示正常的几个函数 2013/06/06 ' 增加了获取控件相关函数是否使用正则的参数UseRegExp默认F ' V1.6 将Left,Top函数改为属性,可获得可设置 2013/06/10 ' V1.7 增加了CloseApp...

    数据结构、算法与应用:C++语言描述(原书第2版)第二部分

    第12章 优先级队列 12.1 定义和应用 12.2 抽象数据类型 12.3 线性表 12.4 堆 12.4.1 定义 12.4.2 大根堆的插入 12.4.3 大根堆的删除 12.4.4 大根堆的初始化 12.4.5 类maxHeap 12.4.6 堆和STL 12.5 左高树 12.5.1 ...

    Python Cookbook

    第12章 XML处理 441 引言 441 12.1 检查XML的格式完好性 443 12.2 计算文档中标签的个数 444 12.3 获得XML文档中的文本 445 12.4 自动探测XML的编码 447 12.5 将一个XML文档转化成Python对象树 449 12.6 从...

    语言程序设计课后习题答案

    面向对象方法所强调的基本原则,就是直接面对客观存在的事物来进行软件开发,将人们在日常生活中习惯的思维方式和表达方式应用在软件开发中,使软件开发从过分专业化的方法、规则和技巧中回到客观世界,回到人们通常...

    超级有影响力霸气的Java面试题大全文档

    派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 3.封装:  封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,...

    Visual C++实践与提高-COM和COM+篇『PDF』

    7.2.1 创建最小的MFC自动化EXE工程 7.2.2 添加COM对象类、接口、属性和方法 7.2.3 在Excel中测试组件 7.3 用ATL开发自动化组件——例程ATLSampleExe 7.3.1 利用ATL COM AppWizard创建进程外组件 7.3.2 分析ATL进程外...

Global site tag (gtag.js) - Google Analytics