Java基础:对象序列化详解

在我们平日开发中,经常让PO类去实现Serializable接口,然后让其可序列化。不过有时我们并不是特别清楚为什么要序列化,特别是对于纯Web项目开发的同学来说,需求环境不一定能用上。下面我简单和大家分享下自己对序列化的认知。

一、什么是序列化

序列化就是把Java对象转换成字节序列的过程。反之,把字节序列恢复成Java对象的过程就叫反序列化

二、为什么要序列化

在网络通信的过程中,我们的数据是需要变成字节序列才能在网络上进行传输。对于消息发送方来说,需要把Java对象转成字节序列才能发送;对于消息接收方来说,则需要把字节序列转成Java对象方能在内存中使用。

另一个场景就是需要把对象数据保存到硬盘,也就是做持久化。因为Java对象是在JVM中生成,属于内存数据,那么要保存到硬盘,则需要把它转换成二进制流(字节序列),也就是序列化。

三、怎样实现序列化

1、实现Serializable或者Externalizable这两个接口当中之一

在Java环境下,需要序列化的类,必须实现Serializable或者Externalizable这两个接口当中之一。Externalizable是继承Serializable,在jdk1.3之前,因Serializable是完全递归的算法导致效率低下,因此Externalizable是一个很好的替换方案。

不过随着jdk版本的性能不断优化,Serializable的性能问题已经得到妥善的解决。现在大多数开发人员都是使用Serializable。

Externalizable反而因其使用操作较为繁琐(需要无参构造方法、重载writeExternal和readExternal实现),而不被广泛使用。

package serialization;


import java.io.Serializable;

public class Boy  implements Serializable {

    private static final long serialVersionUID = -1886667037093879690L;
    private String name = null;
    private  Integer age = null;
    public Boy(){
        System.out.println("无参构造");
    }
    public Boy(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "[" + name + ", " + age+"]";
    }
}

2、序列化

Java中,我们使用ObjectOutputStream这个类进行序列化。通过把需要序列化的对象作为参数,传给writeObject方法。补偿一点的是ObjectOutputStream代表着对象输出流,它可以把对象写入到目标输出流里面。

        //文件保存着字节序列
        File file = new File("Boy.txt");
        //序列化持久化对象
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
        Boy boy = new Boy("Mark", 18);
        out.writeObject(boy);
        out.close();

3、反序列化

与序列化ObjectOutputStream类相对应的,ObjectInputStream用于反序列化。我们可以调用它的readObject方法来读取字节序列,然后把该序列反序列化成对象。

 //反序列化,并得到对象
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
        // 没有强制转换到Person类型
        Object newBoy = in.readObject();
        in.close();
        System.out.println(newBoy);

4、运行结果

a、生成boy.txti

b.反序列化并打印相关信息:

[Mark, 18]

四、注意点:

1、被transient关键字和修饰的属性将不会被序列化

并不是对象所有属性我们都想进行序列化的,比如账号的密码。对于这种情况我们可以用transient来修饰,那么这个字段就不会被序列化。

运行结果:

[null, 18]

2、反序列化过程中,被没有调用对象的构造方法。

在发序列化过程中,被没有调用包括无参构造方法在内的所有构造器。这点从运行结果看出没有执行无参构造方法。

序列化的目的之一就是记录对象当时的状态,而构造方法有可能会对这个状态产生影响,因此反序列化时会调用native方法去处理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值