Java 对象的序列化和反序列化是一种将对象转换成字节流并存储在硬盘或网络中,以及从字节流中从新加载对象的操作。Java 的序列化和反序列化提供了一种不便的形式,使得能够将对象在不同的应用程序之间进行交互。
一、什么是 Java 序列化和反序列化?
Java 对象的序列化是将 Java 对象转换成字节流的过程,可用于长久化数据,传输数据等。序列化是将 Java 对象的状态示意为字节序列的过程,能够通过网络传送,存储到文件中或者应用其余的长久化技术,如数据库等。序列化后的字节流能够被传输给近程零碎,并在那里从新结构成原始对象。Java 序列化是一个将对象转化为字节流的过程。
Java 对象的反序列化是将字节流从新复原为原始对象的过程。反序列化是将字节流转化为对象的过程。反序列化是对象序列化的逆过程,通过反序列化操作可能在接收端复原出与发送端雷同的对象。当咱们须要对存储的对象进行读取操作时,就须要对序列化的字节流进行反序列化操作,将字节流转化为原始的对象信息。
二、序列化和反序列化的实现形式
Java 中的序列化和反序列化能够通过实现 Serializable 接口来实现。Serializable 是一种标记接口,它没有办法定义,但它具备一个特地的作用,就是用于在形容 java 类可序列化时做类型判断的信息。当一个类实现 Serializable 接口时,表明这个类是可序列化的。Serializable 接口只是一个标识接口,咱们并不需要重载任何办法。
在实现 Serializable 接口后,就能够通过 ObjectOutputStream 来将对象序列化,并将序列化后的字节流输入到文件或网络中;同时,也能够通过 ObjectInputStream 来将序列化后的字节流反序列化成对象。
java.io.ObjectOutputStream 继承自 OutputStream 类,因而能够将序列化后的字节序列写入到文件、网络等输入流中。
来看 ObjectOutputStream 的构造方法:ObjectOutputStream(OutputStream out)
一个对象要想序列化,必须满足两个条件:
该类必须实现 java.io.Serializable 接口 open in new window,否则会抛出 NotSerializableException。
该类的所有字段都必须是可序列化的。如果一个字段不须要序列化,则须要应用 transient 关键字 open in new window 进行润饰。
该构造方法接管一个 OutputStream 对象作为参数,用于将序列化后的字节序列输入到指定的输入流中。
示例代码如下:
import java.io.*;
public class SerializationDemo {
public static void main(String[] args) {
// 序列化对象
Person person = new Person("Tom", 20);
try {ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("person.txt"));
objectOutputStream.writeObject(person);
objectOutputStream.close();} catch (IOException e) {e.printStackTrace();
}
// 反序列化对象
try {ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("person.txt"));
Person restoredPerson = (Person) objectInputStream.readObject();
System.out.println(restoredPerson);
objectInputStream.close();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();
}
}
}
class Person implements Serializable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
复制代码
在上述代码中,咱们定义了一个 Person 类,该类实现了 Serializable 接口。在序列化过程中,咱们应用 ObjectOutputStream 类将 person 对象写出到文件中;在反序列化过程中,咱们应用 ObjectInputStream 类读取文件中的字节流,并将其转换为 Person 对象。
三、序列化和反序列化的注意事项
私有化序列号属性
序列化和反序列化须要应用对象的序列号属性(serialVersionUID)来判断版本号是否统一,从而避免在新版本和旧版本之间产生不兼容的状况。如果没有显式地申明 serialVersionUID,则编译器会主动生成一个 serialVersionUID,但这种形式是不牢靠的,因为在批改过程中可能会产生 serialVersionUID 的变动,从而导致不兼容问题。
因而,在 Java 序列化中,最好显式地申明 serialVersionUID 属性,并进行私有化,防止意外的批改。例如:
private static final long serialVersionUID = 1L;
复制代码
实现 readObject 和 writeObject 办法
readObject 和 writeObject 是在序列化和反序列化过程中用于自定义序列化的办法。通常状况下,咱们能够间接应用默认的序列化办法,然而有时咱们须要对序列化内容进行一些解决,这时就须要实现 readObject 和 writeObject 办法。例如,对于对象中敏感数据的解决,咱们能够在 writeObject 办法中对数据进行加密解决,在 readObject 办法中解密解决。
须要留神的是,在实现 readObject 和 writeObject 办法时,必须要调用默认办法,默认办法能够通过 ObjectInputStream 和 ObjectOutputStream 类的 defaultReadObject 和 defaultWriteObject 办法调用。
四、序列化和反序列化的长处和毛病
序列化和反序列化的长处是:
对象的序列化不便了对象在不同利用之间的传递、存储和复原。
通过序列化能够实现分布式计算,在不同的机器上对同一对象进行操作和合作。
序列化提供了数据长久化的能力,行将对象的状态保留在硬盘等介质中,下次能够间接从硬盘中读取数据,防止了频繁地进行数据库读写操作。
序列化和反序列化的毛病是:
在进行序列化和反序列化操作时,须要耗费额定的工夫和开销,特地是当对象比拟大或者嵌套较深的时候,可能会导致重大的性能问题。
序列化和反序列化可能存在安全性问题,如果被攻击者篡改了序列化后的字节流数据,那么反序列化后的对象可能会出现意外行为,如取得不应该取得的权限。
五、总结
Java 对象的序列化和反序列化是一种将对象转换成字节流并存储在硬盘或网络中,以及从字节流中从新加载对象的操作。序列化和反序列化均须要实现 Serializable 接口,并应用 ObjectOutputStream 和 ObjectInputStream 类来实现。序列化和反序列化能够不便地实现对象在不同利用之间的传递、存储和复原等性能,但也存在一些毛病,如可能会导致重大的性能问题和安全性问题。在应用过程中,须要依据具体的业务场景和需要进行抉择和优化,以达到最佳的成果。
在理论的 Java 开发中,序列化和反序列化是一个十分常见的操作,例如在分布式系统中,须要将对象序列化后通过网络传输,在不同的机器上进行反序列化以失去原始对象。
以下是一些应用序列化和反序列化的示例场景:
缓存
在理论的开发中,咱们常常须要对一些数据进行缓存,应用序列化能够将对象序列化为字节数组,而后将字节数组存储到文件或者缓存中。当须要应用缓存中的对象时,再进行反序列化操作,从新取得原始对象。
近程调用
在分布式系统中,须要将对象序列化后通过网络传输,在不同的机器上进行反序列化以失去原始对象。例如在 Dubbo 框架中,就应用了对象序列化和反序列化机制。
长久化数据
在理论的开发中,咱们须要将某些对象的状态保留到数据库或者文件中,应用序列化能够将对象序列化为字节数组,而后将字节数组存储到数据库或者文件中。当须要读取数据时,再进行反序列化操作,取得原始对象。
个别应用 Java 序列化和反序列化只须要实现 Serializable 接口即可,然而也能够应用一些工具依赖来简化操作。以下是一些罕用的序列化和反序列化工具依赖:
- Jackson
Jackson 是一个十分罕用的序列化和反序列化工具,在 Spring Boot 等框架中也被宽泛应用。Jackson 能够将对象序列化为 JSON 或者 XML 格局,同时也能够将 JSON 或者 XML 反序列化为对象。 - Gson
Gson 是另一个罕用的序列化和反序列化工具,同样能够将对象序列化为 JSON 格局,也能够将 JSON 反序列化为对象。 - Protobuf
Protobuf 是 Google 开源的一种轻量级、高效、可扩大的序列化框架,反对多种编程语言。与 Java 序列化相比,Protobuf 应用效率更高,序列化后的字节流更小,但须要预约义音讯格局。 - Kyro
Kryo 是一个高性能的 Java 序列化和反序列化工具,能够将 Java 对象序列化为字节数组,适宜于网络通信和数据长久化等场景。Kryo 可能疾速地序列化和反序列化 Java 对象,绝对于 Java 自带的序列化机制,它的速度更快,序列化后的字节数组也更小。
以上是一些罕用的序列化和反序列化工具依赖,依据不同的业务需要和场景须要抉择适宜的工具。