Java零基础-序列化
  CzYRWOUFyETw 2023年12月15日 10 0

前言

随着计算机技术的飞速发展,互联网的不断普及,数据处理和传输变得越来越重要。为了保证数据的安全传输和存储,我们需要一种方法来对数据进行编码和解码。而序列化就是一种将对象转化为可传输和存储的二进制格式的方式。在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中序列化的基础概念和原理,并详细解析了序列化类的代码和方法。另外,我们还讨论了序列化的优缺点以及应用场景。通过一个测试用例来验证序列化的正确性。在日常开发中,序列化是非常重要的技术,希望本文对大家有所帮助。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月15日 0

暂无评论

推荐阅读
  bVJlYTdzny4o   9天前   21   0   0 Java
CzYRWOUFyETw