background image

可变的对象(如字符串),也要返回一个副本这样调用者不能修改数组中的字符串。不要
传回一个数组,而是数组的拷贝。

不要直接在用户提供的数组里存储
该惯例仅仅是不可变惯例的另一个变型。使用对象数组的构造器和方法,比如说
PubicKey 数组,应当在将数组存储到内部之前克隆数组,而不是直接将数组引用赋给同
样类型的内部变量。缺少这个警惕,用户对外部数组做得任何变动(在使用讨论中的构造
器创建对象后)可能意外地更改对象的内部状态,即使该对象可能是无法改变的

序列化
当对对象序列化时,直到它被反序列化,它不在 Java 运行时环境的控制之下,因此也不
在 Java 平台提供的安全控制范围内。
在实现 Serializable 时务必将以下事宜牢记在心:
•        transient

在包含系统资源的直接句柄和相对地址空间信息的字段前使用 transient

 

关键字。如果资

源,如文件句柄,不被声明为 transient,该对象在序列化状态下可能会被修改,从而使
得被反序列化后获取对资源的不当访问。

•        特定类的序列化/反序列化方法

为了确保反序列化对象不包含违反一些不变量集合的状态,类应该定义自己的反序列化
方法并使用 ObjectInputValidation 接口验证这些变量。

如果一个类定义了自己的序列化方法,它就不能向任何 DataInput/DataOuput 方法传
递内部数组。所有的 DataInput/DataOuput 方法都能被重写。注意默认序列化不会向
DataInput/DataOuput 字节数组方法暴露私有字节数组字段。

如果 Serializable 类直接向 DataOutput(write(byte [] b))方法传递了一个私有数组,
那么黑客可以创建 ObjectOutputStream 的子类并覆盖 write(byte [] b)方法,这样他
可以访问并修改私有数组。下面示例说明了这个问题。
你的类: 
      public class YourClass implements Serializable {

            private byte [] internalArray;
....
private synchronized void writeObject(ObjectOutputStream stream) {
 ...

               stream.write(internalArray);
                ...
}