第74条:谨慎地实现Serializable接口:
第75条:考虑使用自定义的序列化形式:
public final class StringList implements Serializable { private transient int size = 0; private transient Entry head = null; // No longer Serializable! private static class Entry { String data; Entry next; Entry previous; } // Appends the specified string to the list public final void add(String s) { // Implementation omitted } /** * Serialize this {@code StringList} instance. * * @serialData The size of the list (the number of strings it contains) is * emitted ({@code int}), followed by all of its elements (each * a {@code String}), in the proper sequence. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(size); // Write out all elements in the proper order. for (Entry e = head; e != null; e = e.next) s.writeObject(e.data); } private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); int numElements = s.readInt(); // Read in all elements and insert them in list for (int i = 0; i < numElements; i++) add((String) s.readObject()); } private static final long serialVersionUID = 93248094385L; // Remainder omitted }
第76条:保护性地编写readObject方法:
public final class Period implements Serializable { private Date start; private 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 */ public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); if (this.start.compareTo(this.end) > 0) throw new IllegalArgumentException(start + " after " + end); } public Date start() { return new Date(start.getTime()); } public Date end() { return new Date(end.getTime()); } public String toString() { return start + " - " + end; } // readObject method with defensive copying and validity checking - Page 306 // This will defend against BogusPeriod and MutablePeriod attacks. private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); // Defensively copy our mutable components start = new Date(start.getTime()); end = new Date(end.getTime()); // Check that our invariants are satisfied if (start.compareTo(end) > 0) throw new InvalidObjectException(start + " after " + end); } }
第77条:对于实例控制,枚举类型优先于readResolve
还是那句话,单例模式用enum实现最好。
第78条:考虑用序列化代理代替序列化实例,序列化最佳实践:
首先,为可序列化类设计一个私有的静态嵌套类,精确表示外围类的实例的逻辑状态,被称作序列化代理。它有一个单独构造器,参数类型就是外围类。外围类和序列代理都实现Serializable接口。
其次,外围类增加writeReplace方法,返回序列代理对象
再次,外围类增加readObject方法,直接抛异常,防止攻击
最后,序列代理类提供readResolve方法,返回逻辑上相当的外围类实例。
public final class Period implements Serializable { private final Date start; private final 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 */ public Period(Date start, Date end) { this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); if (this.start.compareTo(this.end) > 0) throw new IllegalArgumentException(start + " after " + end); } public Date start() { return new Date(start.getTime()); } public Date end() { return new Date(end.getTime()); } public String toString() { return start + " - " + end; } // Serialization proxy for Period class - page 312 private static class SerializationProxy implements Serializable { private final Date start; private final Date end; SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } private static final long serialVersionUID = 234098243823485285L; // Any // readResolve method for Period.SerializationProxy - Page 313 private Object readResolve() { return new Period(start, end); // Uses public constructor } } // writeReplace method for the serialization proxy pattern - page 312 private Object writeReplace() { return new SerializationProxy(this); } // readObject method for the serialization proxy pattern - Page 313 private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } }
本人博客已搬家,新地址为:http://yidao620c.github.io/
相关推荐
《Effective Java》第三版中文版目录 第一章 介绍 1 第二章 创建和销毁对象 4 1 考虑用静态工厂方法替换构造器 4 2 当遇到多个构造器参
effective-java.pdf
Effective Java读书笔记.pdf
Effective java 3 学习记录
effective java 读书笔记,第二版自己摘要并翻译,以备速查。
Effective Java读书笔记,记载了大部分我觉的有用的东西,前半部分有代码说明,但后半部分的代码,太过琐碎,就没有整理
【Effective Java】阅读笔记markdown 文件
15. 使类和成员的可访问性最小化 16. 在公有类中使用访问方法而非公有域 17.使可变性最小化:不可变类
《Effective Java》读书分享.pptx
Effective-Java:Effective Java的所有练习程序
effective-java 配套代码
Effective STL中文版:50条有效使用STL的经验 高清PDF
Effective Java Effective Java Effective Java
《Effective_C#中文版:改善C#程序的50种方法》读书笔记
effective_java_new:Effective_java_new
构建高效的Java企业级系统是项困难的工作。本书详细介绍企业级计算技术中的常见问题,并描述使用企业级Java平台技术处理这些问题的方法。本书以若干条建议、揸南的形式,言简意赅地介绍了J2EE开发中的微妙之处。无论...
java项目经验源码 Effective Java 作者: 实践《Effective Java》书中的经验法则示例代码,结合Java源码来理解这些最佳实践,并应用于实际项目。 Effective Java, Third Edition Updated for Java 9, Best practices...
java四大名著之一:Effective.Enterprise.Java.中文版 高清pdf 下载