Java零基础-反序列化

举报
喵手 发表于 2024/11/29 00:59:50 2024/11/29
【摘要】 哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这...

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

随着计算机技术的飞速发展,互联网的不断普及,数据处理和传输变得越来越重要。为了保证数据的安全传输和存储,我们需要一种方法来对数据进行编码和解码。而序列化就是一种将对象转化为可传输和存储的二进制格式的方式。在Java的开发中,序列化是一种重要的技术,可以帮助我们实现远程调用、对象存储等功能。

摘要

本文将从Java的序列化基础概念开始,介绍序列化的原理和Java中序列化的方法。接着,我们将讨论序列化的优缺点,并给出一些应用场景案例。最后,我们会详细解析序列化类的代码和方法,并通过测试用例来验证序列化的正确性。

简介

序列化是将对象转化为二进制格式的过程,使得对象可以在网络上传输和存储。在Java中,序列化是利用ObjectOutputStream和ObjectInputStream类实现的。其中,ObjectOutputStream类将对象序列化为二进制流,而ObjectInputStream类则将二进制流反序列化为对象。序列化的基本原理是将对象的状态信息转化为字节流进行传输和存储。在Java中,序列化的过程中还会对对象的类信息进行处理,这使得在反序列化时可以恢复对象的状态信息和类信息。

在Java中,序列化是非常重要的技术,常用于网络通信、对象存储等方面。同时,Java提供了一套完整的序列化机制,使得我们可以方便地对对象进行序列化和反序列化操作。

源代码解析

下面是一个简单的序列化示例代码:

public class Person implements Serializable {
    private String name;
    private int age;
    private String gender;

    // 构造方法
    public Person(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    // getter/setter方法
    // ...

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

在这个示例代码中,我们定义了一个Person类,并实现了Serializable接口。这个接口是Java提供的序列化接口,用于标识一个类可以进行序列化操作。在Person类中,我们定义了三个属性,分别为name、age和gender,同时还提供了getter和setter方法。

下面是一个对象序列化的示例代码:

public class SerializationDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 创建一个Person对象
        Person person = new Person("张三", 18, "男");

        // 创建一个ObjectOutputStream对象
        FileOutputStream fos = new FileOutputStream("person.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        // 将Person对象序列化为二进制流
        oos.writeObject(person);

        // 关闭流
        oos.close();
        fos.close();

        // 创建一个ObjectInputStream对象
        FileInputStream fis = new FileInputStream("person.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);

        // 将二进制流反序列化为Person对象
        Person newPerson = (Person) ois.readObject();

        // 打印Person对象的属性
        System.out.println(newPerson);

        // 关闭流
        ois.close();
        fis.close();
    }
}

在这个示例代码中,我们创建了一个Person对象,并将它序列化为二进制流并保存到磁盘上。接着,我们又通过反序列化的方式将二进制流转换为Person对象,并打印它的属性信息。可以看到,在序列化和反序列化之后,Person对象的属性信息依然保持不变。

应用场景案例

序列化在Java中有着广泛的应用,下面是一些典型的应用场景:

  1. 网络传输:序列化可以将对象转化为可传输的二进制流,使得对象可以通过网络进行传输。在Java的网络编程中,序列化是非常常见的操作,常用于客户端和服务器之间的数据传输。

  2. 对象存储:序列化可以将对象转化为二进制格式的数据,使得它可以被存储在磁盘上。在Java中,序列化经常用于对象的持久化存储,例如Hibernate中就使用了序列化来实现对象的持久化。

  3. 远程调用:序列化可以将对象转化为可传输的二进制格式,使得对象可以在不同的进程之间进行传递。在Java的远程过程调用(RPC)中,序列化是一种关键的技术,可以帮助我们实现远程函数调用。

优缺点分析

序列化作为一种将对象转化为二进制格式的技术,它具有以下优点:

  1. 方便传输和存储:序列化可以将对象转化为二进制格式,使得对象可以在网络上传输和存储,非常方便。

  2. 跨平台兼容性:序列化可以将对象转化为二进制格式,使得它可以在不同的平台之间进行传输和存储,具有很好的兼容性。

  3. 对象持久化:序列化将对象转化为可存储的二进制格式,使得它可以被持久化到磁盘上,长期保存。

当然,序列化也存在一些缺点:

  1. 性能问题:序列化需要将对象转化为二进制格式,这个过程可能会比较耗时,影响程序的性能。

  2. 数据安全问题:序列化将对象转化为可传输和存储的二进制格式,这可能存在数据安全问题,例如数据被窃取或篡改。

类代码方法介绍

ObjectOutputStream和ObjectInputStream类是Java中用于序列化和反序列化操作的关键类,这里我们来详细介绍一下它们的常用方法。

ObjectOutputStream类常用方法

方法名 描述
writeObject() 将对象写入输出流中。
writeInt() 将int类型数据写入输出流中。
writeFloat() 将float类型数据写入输出流中。
writeDouble() 将double类型数据写入输出流中。
writeLong() 将long类型数据写入输出流中。
writeChar() 将char类型数据写入输出流中。
writeUTF() 将字符串写入输出流中。
writeBoolean() 将boolean类型数据写入输出流中。
flush() 刷新输出流,将缓冲区中的数据输出到目标。
close() 关闭输出流,释放资源。当输出流关闭时,会将缓冲区中的数据写入到目标。

ObjectInputStream类常用方法

方法名 描述
readObject() 从输入流中读取对象。
readInt() 从输入流中读取int类型的数据。
readFloat() 从输入流中读取float类型的数据。
readDouble() 从输入流中读取double类型的数据。
readLong() 从输入流中读取long类型的数据。
readChar() 从输入流中读取char类型的数据。
readUTF() 从输入流中读取字符串。

ObjectOutputStream类常用方法

writeObject(Object obj)

将对象写入ObjectOutputStream中。如果该对象实现了Serializable接口,则可以进行序列化。

Person person = new Person("张三", 18, "男");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"));
oos.writeObject(person);
oos.close();

writeInt(int value)

将int类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeInt(10);
oos.close();

writeFloat(float value)

将float类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeFloat(3.14f);
oos.close();

writeDouble(double value)

将double类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeDouble(3.141592653589793);
oos.close();

writeLong(long value)

将long类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeLong(123456789L);
oos.close();

writeChar(char value)

将char类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeChar('A');
oos.close();

writeUTF(String str)

将字符串写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeUTF("Hello World!");
oos.close();

writeBoolean(boolean value)

将boolean类型数据写入ObjectOutputStream中。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeBoolean(true);
oos.close();

flush()

刷新输出流,将缓冲区中的数据输出到目标。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeObject(new Person("张三", 18, "男"));
oos.flush();
oos.close();

close()

关闭输出流,释放资源。当输出流关闭时,会将缓冲区中的数据写入到目标。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.ser"));
oos.writeObject(new Person("张三", 18, "男"));
oos.close();

ObjectInputStream类常用方法

readObject()

从ObjectInputStream中读取对象。如果该对象实现了Serializable接口,则可以进行反序列化。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"));
Person person = (Person) ois.readObject();
ois.close();
System.out.println(person);

readInt()

从ObjectInputStream中读取int类型的数据。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
int value = ois.readInt();
ois.close();
System.out.println(value);

readFloat()

从ObjectInputStream中读取float类型的数据。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
float value = ois.readFloat();
ois.close();
System.out.println(value);

readDouble()

从ObjectInputStream中读取double类型的数据。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
double value = ois.readDouble();
ois.close();
System.out.println(value);

readLong()

从ObjectInputStream中读取long类型的数据。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
long value = ois.readLong();
ois.close();
System.out.println(value);

readChar()

从ObjectInputStream中读取char类型的数据。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
char value = ois.readChar();
ois.close();
System.out.println(value);

readUTF()

从ObjectInputStream中读取字符串。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
String str = ois.readUTF();
ois.close();
System.out.println(str);

available()

返回可以读取的字节数。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
int num = ois.available();
ois.close();
System.out.println(num);

close()

关闭输入流,释放资源。

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"));
Person person = (Person) ois.readObject();
ois.close();

测试用例

下面我们来通过一个测试用例来验证序列化的正确性:

public class SerializationTest {
    @Test
    public void testSerialization() throws IOException, ClassNotFoundException {
        // 创建一个Person对象
        Person person = new Person("张三", 18, "男");

        // 将Person对象序列化为二进制流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(person);

        // 将二进制流反序列化为Person对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        Person newPerson = (Person) ois.readObject();

        // 断言新的Person对象和原来的对象相等
        assertEquals(person, newPerson);
    }
}

在这个测试用例中,我们创建了一个Person对象,并将它序列化为二进制流。接着,我们又通过反序列化的方式将二进制流转换为Person对象,并使用断言来判断新的Person对象和原来的对象是否相等。

通过这个测试用例可以看到,序列化和反序列化过程中,Person对象的属性信息没有发生变化,验证了序列化的正确性。

总结

本文介绍了Java中序列化的基础概念和原理,并详细解析了序列化类的代码和方法。另外,我们还讨论了序列化的优缺点以及应用场景。通过一个测试用例来验证序列化的正确性。在日常开发中,序列化是非常重要的技术,希望本文对大家有所帮助。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。