概念
序列化
将对象转换为字节序列的过程叫做对象的序列化。
对象在jvm运行的时候是存在的,但是一旦jvm运行结束之后,对象也会随之消失,那么如果我们不想让这个对象消失,那么就可以将它以字节描述的形式保存下来,这个转换的过程就叫做序列化。
反序列化
将字节序列恢复为对象的过程叫做对象的反序列化。
假如我们想在运行的时候使用已经保存好的对象,那么这个从字节描述转换为对象的过程就叫做反序列化。
用途
对象的序列化操作的主要用途有两种:
- 将对象序列化后永久地保存到硬盘上,比如保存到数据库或是保存为文件;
- 将对象序列化后用于网络传输。
实现方式
接口
在Java中,要使一个类可以被序列化/反序列化,共有两种序列化接口可以选择:
Serializable接口;Externalizable接口。
Serializable接口是一个空接口,它的作用是声明当前类可以被序列化和反序列化,序列化操作与反序列化操作使用的是默认规则。
/*
* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*/
package java.io;
public interface Serializable {
}
Externalizable接口继承自Serializable接口,包括了两个未实现的方法,用于自定义序列化操作时的规则和反序列化操作时的规则。
/*
* Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*/
package java.io;
import java.io.ObjectOutput;
import java.io.ObjectInput;
public interface Externalizable extends java.io.Serializable {
/**
* The object implements the writeExternal method to save its contents
* by calling the methods of DataOutput for its primitive values or
* calling the writeObject method of ObjectOutput for objects, strings,
* and arrays.
*
* @serialData Overriding methods should use this tag to describe
* the data layout of this Externalizable object.
* List the sequence of element types and, if possible,
* relate the element to a public/protected field and/or
* method of this Externalizable class.
*
* @param out the stream to write the object to
* @exception IOException Includes any I/O exceptions that may occur
*/
void writeExternal(ObjectOutput out) throws IOException;
/**
* The object implements the readExternal method to restore its
* contents by calling the methods of DataInput for primitive
* types and readObject for objects, strings and arrays. The
* readExternal method must read the values in the same sequence
* and with the same types as were written by writeExternal.
*
* @param in the stream to read data from in order to restore the object
* @exception IOException if I/O errors occur
* @exception ClassNotFoundException If the class for an object being
* restored cannot be found.
*/
void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
I/O流类型
序列化对象时我们使用的I/O流类型为ObjectOutputStream类。
反序列化对象操作时我们使用的I/O流类型为ObjectInputStream类。
例子
定义一个对象类Ving类:
package com.vingyun;
import java.io.Serializable;
public class Ving implements Serializable {
/**
* serialVersionUID 序列化与反序列化过程中的类信息校验
*/
private static final long serialVersionUID = 1925138888826980930L;
private String nickName;
private int age;
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.vingyun;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// TODO 自动生成的方法存根
Ving vingSerialize = new Ving();
vingSerialize.setNickName("MasterVing");
vingSerialize.setAge(99);
serializeVing(vingSerialize);
Ving vingDeserialize = null;
vingDeserialize = deserializeVing(vingDeserialize);
System.out.println("NickName: " + vingDeserialize.getNickName() + "\nAge: " + vingDeserialize.getAge());
}
public static void serializeVing(Ving vingSerialize) throws FileNotFoundException, IOException {
ObjectOutputStream obOStream = new ObjectOutputStream(new FileOutputStream("E:/vingInfo.txt"));
obOStream.writeObject(vingSerialize);
obOStream.close();
System.out.println("序列化对象操作完成。\n");
}
public static Ving deserializeVing(Ving vingDeserialize) throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream obIStream = new ObjectInputStream(new FileInputStream("E:/vingInfo.txt"));
vingDeserialize = (Ving) obIStream.readObject();
obIStream.close();
System.out.println("反序列化对象操作完成。\n");
return vingDeserialize;
}
}

相关属性
serialVersionUID
长整型属性serialVersionUID用于序列化与反序列化过程中的类信息校验,如果此属性的值在序列化之后发生了变化,那么已经序列化的文件就不能再反序列化,会抛出InvalidClassException异常。因此,在自定义的可序列化类中虽然不是必须的,但是不同的JVM默认生成的serialVersionUID不一定是完全相同的,因此建议应当显式地声明这个属性,并且用private static final修饰此属性。
serialPersistentFields
ObjectStreamField类型数组serialPersistentFields定义需要被自动序列化的字段,而且一旦定义了这个属性,那么就不会识别原本默认的可序列化字段,例如非static和非transitent字段。
serialPersistentFields属性需要用private static final修饰。
在本文的例子中,没有使用到serialPersistentFields属性。
相关关键字
transitent
关键字transitent用于将属性修饰为不被默认序列化。
如果在transient关键字的同时定义了serialPersistentFields属性,那么transient关键字会被忽略,并且只有serialPersistentFields属性包含的字段才会被序列化。
在本文的例子中,没有使用到transitent关键字。
本文介绍了Java中的对象序列化和反序列化概念,包括其用途、实现方式及示例代码。序列化是将对象状态转化为字节序列以便持久化存储或网络传输的过程。
321

被折叠的 条评论
为什么被折叠?



