Java - 使可访问性最小化
模块设计是否良好,有个重要的因素在于,相对外部模块是否隐藏内部数据以及实现细节。
设计良好的模块会隐藏实现细节,并将API与其实现隔离开来。
模块之间通过API进行通信,对于内部工作情况互不可见。
即,封装(encapsulation)——软件设计的基本原则之一。
为什么要封装?
通过封装可以有效地接触各个模块之间的耦合关系,使这些模块可以独立地开发、测试、优化、使用、理解和修改。
即:
- 可以增加开发效率,模块可以并行开发。
- 封装可以减轻维护的负担,可以更有效的进行优化,且不会影响其他模块的正确性。
- 提高了软件的可重用性,模块在其他环境中也可以被使用。
(PS:回想我自己以前用php写网站时根本没有这些概念也不影响开发工作。当时觉得没什么,因为是我一个人写的,再加上后来也没有再扩展,于是没有了种种体会。)
可以通过访问控制保证封装。
一个实体的可访问性是通过实体声明所在的位置和访问修饰符共同决定的。
建议尽可能地使每个类或者成员不被外界访问。
对于顶层的类和接口只有两种访问级别:包级私有和公有。
更小的可访问性代表更小的兼容性,在以后发行的版本中可以放心对其进行修改。
如果是公有的,则需要一直考虑客户的行为。(PS:如果一个顶层类只是在某一个类的内部被用到,则可以声明为私有静态内部类。)
比如这样一个类,这样做在以后的版本中便无法改变表示方式,而且无法加入任何约束:
class Point {
public double x;
public double y;
}
于是正如很多人的习惯那样,对于公有类用公有的访问方法替代公有field以保证数据在类内部的灵活性:
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;
}
}
(PS:当然,有些常见的类并没有遵守这一规则比如java.awt.Point、java.awt.Dimension。
但原作者也明确指出这些类不值得效仿。)
如果一个field只能是公有的,且允许将其声明为final,则危害能少一些。
我们仍然可以通过公有的访问方法访问该field。
但不能用公有的setter,而是通过构造器加入约束:
public final class Time {
private static final int HOURS_PER_DAY = 24;
private static final int MINUTES_PER_HOUR = 60;
public final int hour;
public final int minute;
public Time(int hour, int minute) {
if (hour < 0 || hour >= HOURS_PER_DAY)
throw new IllegalArgumentException("Hour: " + hour);
if (minute < 0 || minute >= MINUTES_PER_HOUR)
throw new IllegalArgumentException("Min: " + minute);
this.hour = hour;
this.minute = minute;
}
// Remainder omitted
}
对于成员(field,method,嵌套类,嵌套接口)有4种访问级别:
- private
- package-private(default)
- protected
- public
当设计了类的公有API后,我们将所有成员都变成私有。
然后发现同一个包内的另一个类也需要访问这个成员,于是便修改访问级别。如果这种事情经常发生则应该检查设计是否合理。
虽然package和private级别的成员都是类实现的一部分,不会影响导出的API。
但,该类实现了Serializable时则另当别论。
如果使用protected修饰,则需要注意,该成员时导出的API的一部分。
另外,实例field尽量不要设置为公有。如果一个field不是final或者是一个指向可变对象的final field,公有的访问级别会破坏该field的不可变性,它已不是一个内部的数据表示,而且非线程安全。
当然,这对于长度!=0的数组也是一样的。
如果需要将某数组声明为公有,可以尝试以下方式:
private static final Thing[] PRIVATE_VALUES = {...};
public static final List<Thing> VALUES =
Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
或者可以使用clone,每次都拷贝一个数组:
private static final Thing[] PRIVATE_VALUES = {...};
public static final Thing[] values(){
return PRIVATE_VALUES.clone();
}
Java - 使可访问性最小化的更多相关文章
- 《Effective Java》笔记 使类和成员的可访问性最小化
类和接口 第13条 使类和成员的可访问性最小化 1.设计良好的模块会隐藏所有的实现细节,把它的API与实现清晰的隔离开来,模块之间只通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况: ...
- Effective Java 第三版——15. 使类和成员的可访问性最小化
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- EffectiveJava(13)使类和成员的可访问性最小化
1.为什么要使类和成员可访问性最小化 它可以有效地解除组成系统的各模块之间的耦合关系,使得这些模块可以独立的开发 测试 优化 使用 理解和修改.提高软件的可重用性 2.成员的访问级别 私有(priva ...
- Effective Java —— 使类和成员的可访问性最小化
本文参考 本篇文章参考自<Effective Java>第三版第十五条"Minimize the accessibility of classes and members&quo ...
- Effective Java --使类和成员的可访问性最小化
尽可能地降低可访问性 接口和成员变量访问级别四种访问级别: 私有的(private) --- 只有在生命该成员的顶层类内部才可以访问 包级私有的(package-private) --- 缺省的&qu ...
- Effective Java:Ch4_Class:Item13_最小化类及其成员的可访问性
要区别一个模块是否设计良好,最重要的因素是,对于其他模块而言该模块隐藏其内部数据和其他实现细节的程度.设计良好的模块应该隐藏所有实现细节,将API与其实现清晰地隔离开来.这样,模块之间通过他们的API ...
- Effective Java 第三版——17. 最小化可变性
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Effective Java 第三版——57. 最小化局部变量的作用域
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- VC++ 如何使窗体最大化或是最小化
最大化最小的使得的函数是 ShowWindow函数 ShowWindow(SW_SHOWMINIMIZED);//最小化 ShowWindow(SW_SHOWMAXIMIZED);//最大化 Show ...
随机推荐
- HTTP请求报文支持的各种方法
常见的HTTP方法如下: 1.GET GET是最常用的方法.通常用于请求服务器发送某个资源. 2.HEAD HEAD与GET的行为类似,但服务器在响应中只返回首部,不会返回实体的部分.这就允许客户端在 ...
- 学习xss模拟构造攻击(第一篇)
本文作者:i春秋签约作家——rosectow 0×00前言 XSS又名叫CSS全程(cross site scriptting),中文名跨站脚本攻击,目前网站的常见漏洞之一,它的危害没有像上传漏洞,s ...
- WinForm程序运行 Just-In-Time Exception发生时
debug时运行正常, 但exe程序却发生Just-In-Time Exception (具体是做了异步里面更新画面内容) 解决对策: [app.config]文件: jitDebugging设为tu ...
- 3. STL编程三
1. 算法容器的使用: #include <iostream> #include <functional> #include <vector> #include & ...
- TX2 之tensorflow环境部署
刷机jetpack3.3 首先TX2必须是3.3版本的jetpack,因为截止目前nvidia发布的tensorflow只支持3.3版本的jetpack,刷机的具体步骤可以参考NVIDIA Jetso ...
- [转] ELK 之 Logstash
[From] https://blog.csdn.net/iguyue/article/details/77006201 ELK 之 Logstash 简介: ELK 之 LogstashLogsta ...
- [DPF] DB2 DPF 搭建实战
1. Server 准备 2. NFS 系统设置 3. 创建实例 4. rsh/ssh 5. 测试 Server: 192.168.122.1 dpf01.dpf.com dpf01 192.16 ...
- Touch事件机制
1.概念 Touch事件分发中有三个主角:Activity.ViewGroup和View.Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewG ...
- the unchecked warnings
5.1.9. Unchecked Conversion Let G name a generic type declaration with n type parameters. There is a ...
- 032-IDUtils 工具类模板
模板一: package cn.e3mall.common.utils; import java.util.Random; /** * 各种id生成策略 * @title:IDUtils * @des ...