Serializable接口是否可以实现选择性序列化?

时间:2015-08-04 10:42:26

标签: java serialization

让我们说我的班级MyClass有10个变量。通过使用Serializable标记类,我们将所有10个变量序列化。

我的问题是,有没有办法只序列化其中的一些变量,让我们说5只?

我知道可以通过将变量标记为transient来完成。但我想知道是否还有其他方法可以使用transient关键字。

3 个答案:

答案 0 :(得分:3)

如果您的类实现了Externalizable接口,那么您将更好地控制对象的序列化方式。

请注意,与Serializable不同,Externalizable界面不是标记,您需要实施readExternal()writeExternal()方法,实际上< em>以编程方式选择要序列化的类成员以及如何进行反序列化。

更多信息:

答案 1 :(得分:0)

Java支持自定义序列化。请阅读“自定义默认协议”一节。

  然而,有一个奇怪但狡猾的解决方案。通过使用内置   序列化机制的特点,开发人员可以增强   通过在其类文件中提供两个方法来实现正常过程。   那些方法是:

     

private void writeObject(ObjectOutputStream out)抛出IOException;

     

private void readObject(ObjectInputStream in)抛出IOException,   ClassNotFoundException的;

答案 2 :(得分:0)

要自定义序列化时的选项是使用序列化代理:而不是您的&#34; real&#34;对象,您创建一个序列化的替代品。序列化框架使用writeReplace()/readResolve()方法,允许您完成此操作。

这大致如下:

public class Foo implements Serializable {
    private final String bar;
    private final String baz;

    private static class FooProxy implements Serializable {
        private final String barBaz;

        private FooProxy(Foo foo) {
           this.barBaz = foo.bar + "|" + foo.baz; //don't do this for real
        }

        private Object readResolve() {
           String [] arr = this.barBaz.split( "|" );
           return new Foo(arr[0], arr[1]);
        }   

    }

    private Object writeReplace() {
        return new FooProxy(this);
    }

    // this method is required to stop a maliciously constructed serialized form to be deserialized
    private void readObject(ObjectInputStream ois) throws InvalidObjectException {
       throw new InvalidObjectException( "Use a proxy." );
    }

}

因此,每次Foo被序列化时,它都会被一个具有完全不同字段的FooProxy对象替换,并且每次FooProxy被反序列化时,它都会被替换使用相应的Foo

这种技术的优点是你可以完全将序列化形式与内部表示分开,允许你任意改变内部表示,只要它可以从序列化形式重建。