JAVA序列化和反序列化

1、什么是序列化和反序列化

序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。 

2、为什么需要序列化与反序列化 

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为对象。其实序列化的目的就是跨进程传递格式化数据 

3、如何实现序列化与发序列化 

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。然后j通过ObjectOutputStream的writeObject方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。通过jObjectInputStream的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。那我们先写个Demo,代码如下:

public class Student implements Serializable {
    private static final long serialVersionUID =1l;
    private int age;
    private String name;
    private String sex;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
public class TestSerializeAndDeserialize {
    public static void main(String[] args) throws Exception {

        SerializePerson();
        Student stu=DeserializePerson();
        System.out.println(stu.getName()+" "+stu.getSex()+" "+stu.getAge());
    }

    private static void SerializePerson() throws IOException {
        Student stu=new Student();
        stu.setAge(10);
        stu.setName("xiaoming");
        stu.setSex("man");
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("E:/Student.txt")));
        oos.writeObject(stu);
        System.out.println("Student对象序列化成功");
        oos.close();
    }
    private static Student DeserializePerson()throws Exception,IOException{
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("E:/Student.txt")));
        Student stu=(Student)ois.readObject();
        System.out.println("Student对象反序列化成功");
        return stu;
    }
}

程序运行结果:

 4.serialVersionUID的作用

s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D​:​ ​序​列​化​的​版​本​号​,凡是实现Serializable接口的类都应有一个表示序列化版本标识符的静态变量。如果没有s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D会怎么样,我们去掉s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D后再运行程序结果如下:

下面我们在Student类新添一个score属性,如下:

然后执行反序列操作,此时就会抛出如下的异常信息:

Exception in thread "main" java.io.InvalidClassException: com.lg.match.Student;
local class incompatible: stream classdesc serialVersionUID = -379872992605699466, 
local class serialVersionUID = 8365482709425766029

 如果添加s​e​r​i​a​l​V​e​r​s​i​o​n​U​I​D,再执行上面操作,运行结果如下:

serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java编译器编译,有可能会导致不同的 serialVersionUID,也有可能相同。为了提高serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。
显式地定义serialVersionUID有两种用途:
         1、 在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
         2、 在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值