序列化 java 问题_浅析Java序列化中的四个常见问题

一、实现对象序列化的方法有哪些?

Java序列化有两种实现方法,一种在类定义的时候实现Serializable接口,另一种是实现Externalizable接口。实现了这两种接口的类的对象便可以转换成字节流或从字节流恢复,不需要在类中增加任何代码。只有极少数情况下带需要定制代码保存或恢复对象状态。

一般选择使用Serializable接口实现序列化,因为该接口不需要实现任何方法;而Externalizable接口定义了writeExternal()和readExternal()方法,实现该接口的类必须要实现这两种方法。

二、如何自定义序列化和反序列化过程?

在对象序列化的过程中,如果涉及一些敏感信息,例如银行卡账号、密码等,则需要考虑到保密和如何防止在传递过程中泄露的问题。使用transient关键字可以保护这些属性,但是这些属性将不会参与序列化过程。此时,可以考虑显示定制序列化和反序列化的过程,在序列化时加入加密、在反序列化时加入解密等操作,而不是使用默认的序列化方式。

对象在序列化和反序列化时,是调用内部的writeObject()和readObject()方法实现的。writeObject()和readObject()方法的定义如下:

private void writeObject(ObjectOutputStream out) throws IOException

private void readObject(ObjectInputStream in) throws IOException        注意:为了防止在对象序列化过程中调用默认的writeObject()和readObject()方法,必须将这两个方法设置为private.

如果显示定制序列化和反序列化过程,只需重写上述两个方法。如果需要在writeObject()方法中使用默认的序列化机制,只需要在writeObject()方法中调用out.defaultWriteObject()方法;同理,在readObject()方法使用默认的序列化机制时,只需在readObject()方法中调用in.defaultReadObject()方法。

在自定义序列化和反序列化的过程中,对于简单类型的属性,必须使用默认的writeInt(int intValue)、readInt(int intValue)等方法对简单类型进行读写操作;而对于引用类型的属性,可以在writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)中使用readObject()和writeObject()方法进行读写。

另外,在文件或者网络中读取属性时,读取的顺序必须与写入的顺序保持一致。         三、在序列化类中添加serialVersionUID属性有什么作用?

serialVersionUID是一个私有的静态final属性,用于表明类之间不同版本的兼容性,该属性不是必须的。当一个类实现了java.io.Serializable接口,但是没有显示定义一个Long类型的serialVersionUID属性,java序列化机制会根据编译的class自动生成一个serialVersionUID作为该类的序列化版本ID号,只有同一次编译生成的class才会生成相同的serialVersionUID。在反序列化过程中,JVM会把传来的字节流中的serialVersionUID与本地类的serialVersionUID进行比较,如果相同就认为版本一致,可以进行反序列化,否则就会出现序列化版本不一致的InvalidClassException异常。如果不希望通过编译来强制划分软件版本,即实现序列化接口的类能够兼容以前版本,只需显示地定义一个名为serialVersionUID、类型为Long的final属性,即可保证相同的版本号,且在进行序列化和反序列化时不会出现InvalidClassException异常。

四、当序列化遭遇继承时,如何正确处理对象序列化过程?

在序列化过程中,如果父类实现了Serializable和Externalizable接口,则其所有子类都将自动实现序列化。

但是,在实际开发中,这是不可取的。因为父类不能强制其所有子类都具有序列化的能力。

如果父类没有序列化,而子类却实现了Serializable接口,那么子类对象也不能序列化。否则,会抛出InvalidClassException异常。

下面,提供一种可行的方法,供大家参考:

第一、编写一个能够实现序列化的子类,首先将自身序列化。

第二、为其父类提供一个无参的构造方法并序列化父类的属性。

public abstract class AbsSuperClass {

protected int superValue;

/**

* 父类无参的构造方法

*/

public AbsSuperClass() {

}

public AbsSuperClass(int superValue) {

this.superValue = superValue;

}

public int getSuperValue() {

return superValue;

}

public void setSuperValue(int superValue) {

this.superValue = superValue;

}

@Override

public String toString() {

return "superValue = " + superValue;

}

}

/**

* 定义子类并显示定义序列化和反序列化过程

* @author gsucbiao

*

* @date 2011-9-7 && 上午12:23:35

*/

public class SubClass extends AbsSuperClass implements Serializable {

private static final long serialVersionUID = 1L;

private int subValue;

public SubClass(int superValue, int subValue) {

super(superValue);

this.subValue = subValue;

}

private void writeObject(ObjectOutputStream out) throws IOException {

out.defaultWriteObject();

out.writeInt(superValue);

}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {

in.defaultReadObject();

superValue = in.readInt();

}

@Override

public String toString() {

return super.toString() + "subValue = " + subValue;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值