Effective Java:Ch4_Class:Item14_在public类中应该使用访问方法而不是public域
你可能偶尔需要编写退化类,目的只是为了集中实例域:
// Degenerate classes like this should not be public!
class Point {
public double x;
public double y;
}
由于这种类的数据域是可以直接访问的,所以他们不能提供“封装”带来的好处。如果不改变API,就不能改变其数据表示法,不能强加任何约束,当域被访问时不能采取任何辅助行为。强硬派的面向对象程序员会非常厌恶这种类,认为这种类应该被包含private域和public访问方法(getter)的类替代。对于可变类,还应该包含setter。
// Encapsulation of data by accessor and mutators
class Point {
private double x;
private double y; public Point(double x, double y) {
this.x = x;
this.y = y;
} public double getX() { return x; }
public double getY() { return y; }
public void setX(double x) { this.x = x; }
public void setY(double y) { this.y = y; }
}
毫无疑问,强硬派的观点在public类上是正确的:如果一个类可以被包外访问,那么就要提供访问方法,以便可以灵活地改变类的内部表示。如果public类暴露了其数据域,则要想在将来改变内部表示是不可能的,因为他的客户端代码可能已经遍布各处了。
然而,如果类是package-private或是private嵌套类,那么把数据域暴露出去并没有本质的错误——假设这些数据域充分描述了该类提供的抽象。无论是在类定义中,还是在客户端代码中,这种方法相对于访问方法更不会产生视觉混乱。虽然客户端代码与类的内部表示紧密相连,但这些代码被限定在同一个包中。如果需要改变内部数据表示,你不必修改包外的任何代码。如果是private嵌套类,则甚至不需要修改类外的任何代码。
JDK中的几个类违反了“public类不应该直接暴漏其字段”这个告诫。最显著的例子是java.awt包中的Point类和Dimension类。正如Item55中讲的,决定暴露Dimentsion类的内部实现造成了严重的性能问题,而且这个问题至今还存在。
——Component.getSize()返回Dimension,每次调用都要new一个新的对象。
虽然直接暴露public类的字段永远都不是个好主意,但是如果该域是不可变的(immutable),则危害性就小得多。除非修改其API,否则你不能修改其内部数据表示,而且当别人读取该字段时 你不能采取任何附加行动,但是你可以强加约束条件(——因为只有你自己可以set该字段)。例如,下面这个类保证了每个实例都表示一个合法的时间。
// public class with exposed immutable fields - questionable
public final class Time {
private static final int HOUR_PER_DAY = 24;
private static final int MINUTES_PER_HOUR = 60; public final int hour;
public final int minute; public Time() {
//强加约束条件
if (hour < 0 || hour >= HOUR_PER_DAY) {
throw new IllegalArgumentException();
if (minute < 0 || minute >= MINUTES_PER_HOUR) {
throw new IllegalArgumentException(); this.hour = hour;
this.minute = minute;
} }
总之,public类永远不要暴露其可变的字段。而public类暴露其不可变字段随然是有问题,但危害性要小一些。然而,package-private或者private的嵌套类暴露其字段则是可行的,无论该字段是可变还是非可变。
Effective Java:Ch4_Class:Item14_在public类中应该使用访问方法而不是public域的更多相关文章
- Effective Java 第三版——16.在公共类中使用访问方法而不是公共属性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- [Effective Java]第三章 对所有对象都通用的方法
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- org.apache.commons.lang3.StringUtils类中isBlank和isEmpty方法的区别
相信很多java程序员在写代码的时候遇到判断某字符串是否为空的时候会用到StringUtils类中isBlank和isEmpty方法,这两个方法到底有什么区别呢?我们用一段代码来阐述这个区别吧: @T ...
- 在eclispe的类中快速打出main方法
在java类中快速打出main方法有两种途径: 1. 在新建类时,在New Java Class窗口中,将public static void main ( String[ ] args ) 前面打上 ...
- 菜鸡的Java笔记 第十三 String 类的两种实例化方法
String 类的两种实例化方法 String 类的两种实例化方式的区别 String 类对象的比较 Stirng 类对象的使用分析 /* 1.String 类的两种实例化方式的区别 ...
- 创建如下三个类:(People类中的三个方法分别输出一些信息,ChinaPeople 和AmericanPeople类重写父类的三个方法)。
创建如下三个类:(People类中的三个方法分别输出一些信息,ChinaPeople 和AmericanPeople类重写父类的三个方法). ackage com.chuoji.text01; pub ...
- UnSafe类中的一些重要方法
UnSafe类中的一些重要方法 JDK中的rt.jar保重Unsafe类中提供了硬件级别的原子性操作,Unsafe类中的方法都是navtice方法,他们使用JNI的方式访问C++实现库,下面我们来了解 ...
- php面向对象类中常用的魔术方法
php面向对象类中常用的魔术方法 1.__construct():构造方法,当类被实例化new $class时被自动调用的方法,在类的继承中可以继承与覆盖该方法,例: //__construct( ...
- 关于Integer类中parseInt()和valueOf()方法的区别以及int和String类性的转换.以及String类valueOf()方法
Integer类中的. 关于parseInt()方法的API文档. 返回的是int类型的 关于valueOf()方法的API文档 返回的是Integer类型的. 关于intValue()方法的API ...
随机推荐
- 【C++实现】HeadFirst策略模式设计模式
策略模式定义了算法家族.分别封装起来.让它们之间能够相互替换,此模式让算法的变化独立于使用算法的客户. Head First设计模式中介绍策略模式时以Duck类作为样例.当中用flyBehavior和 ...
- mysql 数据库插入语句之insert into,replace into ,insert ignore
近期才发现mysql的插入语句竟然有如此多的使用方法,这里拿来分享一下. ①关于insert into : insert into table_name values(); insert into t ...
- .net的自定义JS控件,运用了 面向对象的思想 封装 了 控件(.net自定义控件开发的第一天)
大家好!我叫刘晶,很高兴你能看到我分享的文章!希望能对你有帮助! 首先我们来看下几个例子 ,就能看到 如何 自定义控件! 业务需求: 制作 一个 属于 自己的 按钮 对象 ,然后 像 ...
- centos7看电影
sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm sudo rpm ...
- PL/SQL联系oracle成功可以sql解决的办法是检查表的名称无法显示
有时,因为机器突然断电或其他原因PL/SQL它甚至不能在数据库表后显示.序列和其它元素.使用SQL Windows运行查询一般查询,登录或同样的现象再次. 我是不是可以解决因重复登录的猜测是,PLSQ ...
- C语言编写Windows服务程序
原文:C语言编写Windows服务程序 #include <Windows.h> #include <stdio.h> #define SLEEP_TIME 5000 // 间 ...
- Asp.Net MVC5入门学习系列⑦
原文:Asp.Net MVC5入门学习系列⑦ 接着上篇结尾所说,如果开发中刚才遇到Model需要添加或者减少字段/属性的话,但是刚好你也利用EF的Code frist通过Model生存的数据库,这时改 ...
- 使用Row_Number()分页优化
记一次SQLServer的分页优化兼谈谈使用Row_Number()分页存在的问题 最近有项目反应,在服务器CPU使用较高的时候,我们的事件查询页面非常的慢,查询几条记录竟然要4分钟甚至更长,而且 ...
- 真懂JavaScript吗
你真懂JavaScript http://www.cnblogs.com/elegance/p/4195593.html 看了汤姆大叔的“你真懂JavaScript吗?”,里面有5道题目,我都一一作了 ...
- 轻型ORM--Dapper
分享一个轻型ORM--Dapper选用理由 推荐理由:Dapper只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快:) Google Code下载地址 ...