5.每个可序列化的类都有一个唯一标识号(也被称为序列号版本UID(serial version UID))与它关联,如果你没有一个名为serialVersionUID的私有静态final的long域显式地指定该标识号,系统就会自动根据这个类来调用一个复杂的运算过程,从而在运行时产生该标识号,这个自动产生的值会受到类名称,他所实现的接口的名称,以及所有公有和受保护的成员的名称所影响.这个唯一标识号存在的意义就是说唯一标识号相同的类(一个类的原来的实现和更新的实现)才可以相互序列化和反序列化转换(或者说唯一标识号相同的两个实现具有相同的序列化形式),否则就会报InvalidClassException
// Nonserializable stateful class allowing serializable subclasspublicabstractclassAbstractFoo {privateint x, y; // Our state// This enum and field are used to track initializationprivateenum State {
NEW, INITIALIZING, INITIALIZED
};
privatefinal AtomicReference<State> init = new AtomicReference<State>(
State.NEW);
publicAbstractFoo(int x, int y) {
initialize(x, y);
}
// This constructor and the following method allow// subclass's readObject method to initialize our state.protectedAbstractFoo() {
}
protectedfinalvoidinitialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING))
thrownew IllegalStateException("Already initialized");
this.x = x;
this.y = y;
// Do anything else the original constructor did
init.set(State.INITIALIZED);
}
// These methods provide access to internal state so it can// be manually serialized by subclass's writeObject method.protectedfinalintgetX() {
checkInit();
return x;
}
protectedfinalintgetY() {
checkInit();
return y;
}
// Must call from all public and protected instance methodsprivatevoidcheckInit() {
if (init.get() != State.INITIALIZED)
thrownew IllegalStateException("Uninitialized");
}
// Remainder omitted
}
// Serializable subclass of nonserializable stateful classpublicclassFooextendsAbstractFooimplementsSerializable {privatevoidreadObject(ObjectInputStream s) throws IOException,
ClassNotFoundException {
s.defaultReadObject();
// Manually deserialize and initialize superclass stateint x = s.readInt();
int y = s.readInt();
initialize(x, y);
}
privatevoidwriteObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
// Manually serialize superclass state
s.writeInt(getX());
s.writeInt(getY());
}
// Constructor does not use the fancy mechanismpublicFoo(int x, int y) {
super(x, y);
}
privatestaticfinallong serialVersionUID = 1856835860954L;
}
publicfinalclassPeriodimplementsSerializable {privatefinal Date start;
privatefinal Date end;
/**
* @param start
* the beginning of the period
* @param end
* the end of the period; must not precede start
* @throws IllegalArgumentException
* if start is after end
* @throws NullPointerException
* if start or end is null
*/publicPeriod(Date start, Date end) {
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0)
thrownew IllegalArgumentException(start + " after " + end);
}
public Date start() {
returnnew Date(start.getTime());
}
public Date end() {
returnnew Date(end.getTime());
}
public String toString() {
return start + " - " + end;
}
// Serialization proxy for Period class//为可序列化的类设计一个私有的静态嵌套类,精确地表示外围类的实例的逻辑状态.这个嵌套类被称作序列化代理privatestaticclassSerializationProxyimplementsSerializable {privatefinal Date start;
privatefinal Date end;
//他应该有一个单独的构造器,其参数就是那个外围类
SerializationProxy(Period p) {
this.start = p.start;
this.end = p.end;
}
privatestaticfinallong serialVersionUID = 234098243823485285L; // Any// number// will// do// (Item// 75)// readResolve method for Period.SerializationProxy//提供readResolve使得序列化系统在反序列化时将序列化代理转变为外围类的实例private Object readResolve() {
returnnew Period(start, end); // Uses public constructor
}
}
// writeReplace method for the serialization proxy patternprivate Object writeReplace() {
returnnew SerializationProxy(this);
}
// readObject method for the serialization proxy pattern//攻击者可能伪造,所以将readObject变为privateprivatevoidreadObject(ObjectInputStream stream)
throws InvalidObjectException {
thrownew InvalidObjectException("Proxy required");
}
}