转载地址: http://www.blogjava.net/kuuyee/archive/2013/06/14/400560.html
软件设计的基本原则之一,就是系统要模块化,模块之间只通过他们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称作信息隐藏(information hiding)或封装(encapsulation)。
需要遵守的原则
-
尽可能地使每个类或成员不被外界访问。换句话说,应该使用与你正在编写的软件的对应功能相一致、尽可能最小的访问级别。
-
对于顶层的(非嵌套的)类和接口,只有两种可能非访问级别,要从是包级私有的也就是default,要么是public的.包级私有就意味着它是这个包实现的一部分,不会作为该包API被导出,这样在以后的发型版本中,对它修改、替换、删除就不用担心会影响先有客户端的程序。
-
如果一个包级私有的顶层类(或者接口)只是在某一个类内部被用到,就应该考虑把它变成唯一使用它的那个类的私有嵌套类。
-
降低不必要公有类的可访问性,比降低包级私有的顶层类更重要的多,因为共有类是API的一部分,而包级私有的顶层类已经是包实现的一部分了。
-
受保护(protected)的类或成员是导出API的一部分,必须永远得到支持,应该避免尽量少用。
-
如果子类覆盖了超类的一个方法,子类中的访问级别就不允许低于超类中的访问级别,否则会编译错误。实现了接口的所有方法也必须是共有的,因为接口中的所有方法都是隐含着共有访问级别。
-
为了便于测试,不应该把其访问级别成为共有的,取而代之是把测试类成为包的一部分,从而能够访问它的包级私有元素。
-
实例域决不能是共有的,包含公有可变域的类即便是final的也不是线程安全的,
Note | 长度非零的数组总数可变的,所以,类具有公有的静态final数组域,或者返回这种域的访问方法,这几乎总数错误的。 |
public class UnmodifiableArray {
// 潜在安全漏洞
public static final String[] VALUES = { "RED", "GREEN" };
public static void main(String[] args) {
UnmodifiableArray UF = new UnmodifiableArray();
UF.VALUES[1] = "YELLO";//设置final数组成员
System.out.println(UF);
}
//使用Guava
@Override
public String toString() {
return Objects.toStringHelper(this).add("VALUES0", UnmodifiableArray.VALUES[0])
.add("VALUES1", UnmodifiableArray.VALUES[1]).toString();
}
}
上面的例子里,我们成功更改了一个不可变数组,把成员GREEN修改为YELLO,执行输出如下:
UnmodifiableArray{VALUES0=RED, VALUES1=YELLO}
我们可以通过增加一个不可变集合列表来解决这个安全问题,并把原来public访问级别改为private的:
public class UnmodifiableArrayList {
// 消除安全漏洞
private static final String[] PRIVATE_VALUES = { "RED", "GREEN" };
public static final List<String> PVALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
public static void main(String[] args) {
UnmodifiableArrayList UF = new UnmodifiableArrayList();
UF.PVALUES.add(1, "YELLO"); //会抛出UnsupportedOperationException异常
System.out.println(UF);
}
//使用Guava
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("PVALUES0", UnmodifiableArrayList.PVALUES.get(0))
.add("PVALUES1", UnmodifiableArrayList.PVALUES.get(1))
.toString();
}
}
构建一个不可变集合,Guava给出了更简洁的办法:
ImmutableList mmutableList = ImmutableList.of(PRIVATE_VALUES);