Effective Java 74 Implement Serializable judiciously

Disadvantage of Serializable

  1. A major cost of implementing Serializable is
    that it decreases the flexibility to change a class‘s implementation once it
    has been released.

    If you accept the default serialized form, the
    class‘s private and package-private instance fields become part of its
    exported API, and the practice of minimizing access to fields (Item
    13
    ) loses its effectiveness as a tool for information hiding.

    It is possible to change the internal
    representation while maintaining the original serialized form (using

    ObjectOutputStream.putFields and
    ObjectInputStream.readFields ), but it can be difficult and leaves visible
    warts in the source code.

    stream unique identifiers (serial
    version UIDs)

    If you do not specify this number explicitly by
    declaring a static final long field named serialVersionUID , the system
    automatically generates it at runtime by applying a complex procedure to the
    class.

    The automatically generated value is affected
    by the class‘s name, the names of the interfaces it implements, and all of

    its public and protected members. If you fail
    to declare an explicit serial version UID, compatibility will be broken,
    resulting in an InvalidClassException at runtime.


  2. A second cost of implementing Serializable is
    that it increases the likelihood of bugs and security holes.

    Objects are created using constructors;
    serialization is an extralinguistic mechanism for creating objects. Relying on
    the default deserialization mechanism can easily leave objects open to
    invariant corruption and illegal access (Item 76).


  3. A third cost of implementing Serializable is
    that it increases the testing burden associated with releasing a new version
    of a class.

    When a serializable class is revised, it is
    important to check that it is possible to serialize an instance in the new
    release and deserialize it in old releases, and vice versa.

Principle

  1. Classes designed for inheritance (Item
    17
    ) should rarely implement Serializable, and interfaces should rarely
    extend it.

  2. If the class has invariants that would be
    violated if its instance fields were initialized to their default values (zero
    for integral types, false for boolean, and null for object reference types),
    you must add this readObjectNoData method to the class.

    // readObjectNoData for stateful
    extendable serializable classes

    private void readObjectNoData() throws
    InvalidObjectException {

    throw new InvalidObjectException("Stream data
    required");

    }

If a class that is designed for inheritance is
not serializable, it may be impossible to write a serializable subclass.
Specifically, it will be impossible if the superclass does not provide an
accessible parameterless constructor.

You should consider providing a
parameterless constructor on nonserializable classes designed for inheritance .

// Nonserializable stateful class allowing
serializable subclass

public abstract class AbstractFoo {

private int x, y; //
Our state

// This enum and field
are used to track initialization

private enum State {
NEW, INITIALIZING, INITIALIZED };

private
final AtomicReference<State> init = new
AtomicReference<State>(State.NEW);

public AbstractFoo(int
x, int y) { initialize(x, y); }

// This constructor
and the following method allow

// subclass‘s
readObject method to initialize our state.

protected
AbstractFoo() { }

protected final void
initialize(int
x, int y) {

if
(!init.compareAndSet(State.NEW, State.INITIALIZING))

throw new
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.

protected final int
getX() {
checkInit(); return x; }

protected final int
getY() { checkInit(); return y;
}

// Must call
from all public and protected instance methods

private void
checkInit() {

if
(init.get() != State.INITIALIZED)

throw
new IllegalStateException("Uninitialized");

}

... // Remainder
omitted

}

// Serializable subclass of nonserializable
stateful class

public class Foo extends
AbstractFoo
implements Serializable {

private void
readObject(ObjectInputStream s)

throws IOException,
ClassNotFoundException {

s.defaultReadObject();

// Manually
deserialize and initialize superclass state

int x =
s.readInt();

int y =
s.readInt();

initialize(x,
y);

}

private void
writeObject(ObjectOutputStream s)

throws IOException {

s.defaultWriteObject();

// Manually
serialize superclass state

s.writeInt(getX());

s.writeInt(getY());

}

// Constructor
does not use the fancy mechanism

public Foo(int x, int
y) { super(x, y); }

private static
final long serialVersionUID = 1856835860954L;

}

Inner classes(Item
22
) should not implement Serializable.
A static member class can,
however, implement Serializable.

Summary

Unless a class is to be thrown away after a short
period of use, implementing Serializable is a serious commitment that should be
made with care. Extra caution is warranted if a class is designed for
inheritance. For such classes, an intermediate design point between implementing
Serializable and prohibiting it in subclasses is to provide an
accessible parameterless constructor.
This design point permits, but
does not require, subclasses to implement Serializable.

Effective Java 74 Implement Serializable judiciously

时间: 2024-11-05 12:20:06

Effective Java 74 Implement Serializable judiciously的相关文章

Effective Java 目录

<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating and Destroying Objects Consider static factory methods instead of constructors Consider a builder when faced with many constructor parameters Enforce the s

Effective Java 71 Use lazy initialization judiciously

Lazy initialization - It decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing the lazily initialized field. Depending on what fraction of lazily initialized fields eventually require i

【电子书】Effective Java中文版下载

下载地址: 点击打开链接 (需要资源0分的联系我~) <Effective Java中文版(第2版)>主要内容:在Java编程中78条极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案.通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰.健壮和高效的代码.第2版反映了Java 5中最重要的变化,并删去了过时的内容. <Effective Java中文版(第2版)>中的每条规则都以简短.独立的小文章形式出现,并

《Effective Java(中文第二版)》【PDF】下载

<Effective Java(中文第二版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382186 Java(中文第二版)>[PDF]"  TITLE="<Effective Java(中文第二版)>[PDF]" /> 编辑推荐 <Sun 公司核心技术丛书:EffectiveJava中文版(第2版)>内容全面,结构清晰,讲解详细.可作为技术人员的参考用书.编码平添乐

Effective Java 第三版——19. 如果使用继承则设计,并文档说明,否则不该使用

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 19. 如果使用继承则设计,并文档说明,否则不该使用 条目 18中提醒你注意继承没有设计和文档说明的"外来"类的子类化的危险. 那么为了继承而设计和文档

effective java

1.考虑用静态工厂方法代替构造函数 对于一个类,为了让客户获得他的一个实例,最通常的方法是提供一个共有的构造函数. 实际上还有另外一种技术,尽管较少为人所知,但也应该成为每个程序员的工具箱中的一 部分,类可以提供一个公有的  静态工厂方法 .所谓静态工厂方法,实际上只是一个简单 的静态方法,他返回的是类的一个实例. 类可以提供一些静态工厂方法,来代替构造函数,或者同时也提供好一些构造函数.用静态 工厂来代替公有的构造函数,既有好处,也有不足之处. 静态工厂方法的一个好处是,与构造函数不同,静态工

Effective Java 读书笔记(一):使用静态工厂方法代替构造器

这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文<java中final与static的使用场景总结>. 什么是静态工厂方法? 可以参考书中的例子(摘自JDK1.7 java.lang.Boolean) public final class Boolean implements java.io.Serializable, Comparable<

Effective Java读后感

<Effective Java>读后感 1       创建和销毁对象 1.1    考虑用静态工厂方法代替构造器 静态工厂方法优点: 静态工厂方法与构造器(构造方法)不同的第一大优势在于,它们有名称.见名知意,突出区别. 静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新对象. 静态工厂方法与构造器不同的第三大优势在于,它们可以返回原返回类型的任何子类型的对象. 静态工厂方法与构造器不同的第四大优势在于,在创建参数化类型实例的时候,它们使代码变得更加简洁. 例如:

Effective Java Item7:Avoid Finalizers,解释为什么finalize是不安全的,不建议使用

我的上一篇博客:System.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放 在讨论如何回收堆外内存的时候,提到"NIO中direct memory的释放并不是通过finalize(),因为finalize不安全而且影响能".Effective Java一书中也提到:Avoid Finalizers.人都有潜在的叛逆意识,别人给的结论或者制定的规范,除非有足够的理由说服你,除非懂得这么做背后的原因,否则只能是死记硬背,没有