序列化、反序列化

一、序列化、反序列化概念

序列化(Serialization)是一种将对象以一连串的字节描述的过程,将程序中的对象,放入硬盘(文件)中保存就是序列化,如果不存放在磁盘中,而是一直存放在内存中,会增大内存的消耗;序列化就是将对象的状态信息转换为可以存储或传输的形式的过程;

反序列化(Deserialization)是一种将这些字节重建成一个对象的过程,将硬盘(文件)中的字节码重新转成对象就是反序列化。

在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

  • 把对象的字节序列永久保存到硬盘上,通常存放在一个文件中(序列化对象)

  • 在网络上传送对象的字节序列(网络传输对象) 实际上就是将数据持久化,防止一直存储在内存当中,消耗内存资源。而且序列化后也能更好的便于网络运输何传播

  • 序列化:将java对象转换为字节序列

  • 反序列化:把字节序列回复为原先的java对象

在这里插入图片描述

二、实现序列化

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常

import java.io.Serializable;
public class ZslTest implements Serializable {
    private String name;
    private Integer age;
    private Integer score;

    @Override
    public String toString() {
        return "ZslTest{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }
}

测试类

import java.io.*;

public class test01 {
    public static void serialize(  ) throws IOException {

        ZslTest ZslTest = new ZslTest();
        ZslTest.setName("linko");
        ZslTest.setAge( 18 );
        ZslTest.setScore( 1000 );

        ObjectOutputStream objectOutputStream =
                new ObjectOutputStream( new FileOutputStream( new File("ZslTest.txt") ) );
        objectOutputStream.writeObject( ZslTest );
        objectOutputStream.close();

        System.out.println("序列化成功!已经生成ZslTest.txt文件");
        System.out.println("==============================================");
    }

    public static void deserialize(  ) throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream =
                new ObjectInputStream( new FileInputStream( new File("ZslTest.txt") ) );
        ZslTest ZslTest = (ZslTest) objectInputStream.readObject();
        objectInputStream.close();

        System.out.println("反序列化结果为:");
        System.out.println( ZslTest );
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        serialize();
        deserialize();
    }
}

结果:
在这里插入图片描述
从上面可知:
JDK类库提供的序列化API

java.io.ObjectOutputStream:表示对象输出流 它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream:表示对象输入流
它的readObject()方法从源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。

直接总结:

  • 若对象仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化。 ObjectOutputStream采用默认的序列化方式,对象的非transient的实例变量进行序列化
    ObjcetInputStream采用默认的反序列化方式,对象的非transient的实例变量进行反序列化
  • 若对象仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
    ObjectOutputStream调用对象的(重写可能存在反序列化风险writeObject(ObjectOutputStream out)的方法进行序列化
    ObjectInputStream会调用对象的(重写可能存在反序列化风险readObject(ObjectInputStream in)的方法进行反序列化
  • 若对象实现了Externalnalizable接口,且对象必须实现readExternal(ObjectInput in)writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。
    ObjectOutputStream调用对象的(重写可能存在反序列化风险writeExternal(ObjectOutput out)的方法进行序列化
    ObjectInputStream调用对象的(重写可能存在反序列化风险readExternal(ObjectInput in)的方法进行反序列化
  • Serializable接口是个空接口,他是一个标记接口,只是做一个标记用!告诉代码只要是实现了Serializable接口的类都是可以被序列化的,然而真正的序列化动作不需要靠它完成。
    在这里插入图片描述
    跟踪源码到ObjectOutputStreamwriteObject0()
    在这里插入图片描述
    在这里插入图片描述

三、序列化的必要条件

  • 必须是同包,同名。
  • serialVersionUID必须一致。有时候两个类的属性稍微不一致的时候,可以通过将此属性写死值,实现序列化和反序列化。

证明serialVersionUID必须一致:
先手动给ZslTest对象加上serialVersionUID,序列化
在这里插入图片描述
在这里插入图片描述
手动删掉serialVersionUID
在这里插入图片描述
注释掉序列化,直接反序列化前面已经序列化的对象
在这里插入图片描述
总结:

  • serialVersionUID是序列化前后的唯一标识符
  • 默认如果没有人为显式定义过serialVersionUID,那编译器会为它自动声明一个!
  • serialVersionUID序列化ID,可以看成是序列化和反序列化过程中的“暗号”,在反序列化时,JVM会把字节流中的序列号ID和被序列化类中的序列号ID做比对,只有两者一致,才能重新反序列化,否则就会报异常来终止反序列化的过程。
  • 为了serialVersionUID的确定性,建议mplements Serializable的对象,都手动显式地为它声明一个serialVersionUID明确值!

四、静态变量序列化、父类序列化、 Transient 关键字

  • 被static修饰的字段是不会被序列化的;
    序列化保存的是对象的状态,静态变量属于类的状态,因此序列化并不保存静态变量

  • 想将父类对象也序列化,就需要让父类也实现Serializable 接口

父类没有实现 Serializable 接口时,JVM是不会序列化父对象的,但是父类不实现Serializable 接口,而他有默认的无参的构造函数,除非在父类无参构造函数中对变量进行初始化,否则父类中的变量值都是默认声明的值,如
int 型的默认是 0,string 型的默认是 null。

因为:Java对象的构造必须先有父对象,才有子对象,反序列化也不例外,所以反序列化时,为了构造父对象,只能调用父类的无参构造函数作为默认的父对象。因此当我们取父对象的变量值时,它的值是调用父类无参构造函数后的值。在父类无参构造函数中对变量进行初始化,
否则的话,父类变量值都是默认声明的值,如 int 型的默认是 0,string 型的默认是 null。

  • Transient 关键字的作用是控制变量的序列化,在变量声明前加上Transient 关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
    在这里插入图片描述

五、关于RMI

RMI相关

RMI 技术是完全基于 Java 序列化技术的,服务器端接口调用所需要的参数对象来至于客户端,它们通过网络相互传输。这就涉及 RMI
的安全传输的问题。一些敏感的字段,如用户名密码(用户登录时需要对密码进行传输),我们希望对其进行加密,这时,就可以采用本节介绍的方法在客户端对密码进行加密,服务器端进行解密,确保数据传输的安全性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity中的序列化(Serialization)是指将对象转换为字节流的过程,而反序列化(Deserialization)则是将字节流转换为对象的过程。Unity提供了一些机制来实现对象的序列化反序列化。 Unity的序列化机制主要用于保存和加载游戏对象的状态,或者在网络传输中传递对象。以下是一些常见的序列化反序列化方法: 1. Unity的内置序列化:Unity提供了内置的序列化机制,使得你可以将脚本中的变量标记为可序列化。通过在变量前面添加 `[SerializeField]` 属性,可以将该变量标记为可序列化。例如: ```csharp [SerializeField] private int score; ``` 2. XML 和 JSON 序列化:Unity还支持使用XML或JSON格式进行序列化反序列化。你可以使用 `System.Xml.Serialization` 命名空间下的类来进行XML的序列化反序列化,或者使用JsonUtility类来进行JSON的序列化反序列化。 ```csharp // XML序列化反序列化示例 using System.Xml.Serialization; // 序列化为XML XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); using (StreamWriter writer = new StreamWriter("data.xml")) { serializer.Serialize(writer, myObject); } // 从XML反序列化 using (StreamReader reader = new StreamReader("data.xml")) { MyClass myObject = (MyClass)serializer.Deserialize(reader); } // JSON序列化反序列化示例 using UnityEngine; using UnityEngine.Networking; // 序列化为JSON string json = JsonUtility.ToJson(myObject); // 从JSON反序列化 MyClass myObject = JsonUtility.FromJson<MyClass>(json); ``` 3. 二进制序列化:如果需要更高效的序列化反序列化操作,可以使用二进制格式。Unity提供了BinaryFormatter类来进行二进制的序列化反序列化。 ```csharp // 二进制序列化反序列化示例 using System.Runtime.Serialization.Formatters.Binary; // 序列化为二进制 BinaryFormatter formatter = new BinaryFormatter(); using (FileStream stream = new FileStream("data.bin", FileMode.Create)) { formatter.Serialize(stream, myObject); } // 从二进制反序列化 using (FileStream stream = new FileStream("data.bin", FileMode.Open)) { MyClass myObject = (MyClass)formatter.Deserialize(stream); } ``` 这些是Unity中常用的序列化反序列化方法,你可以根据具体的需求选择适合的方法来实现对象的序列化反序列化

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷学习被我发现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值