
一Java序列化与反序列化1.Serialization序列化Java序列化是指将Java对象转换为字节流的过程以便将对象的状态保存到文件、数据库或通过网络传输。序列化后的字节流包含对象的数据及其类型信息使得对象可以在不同JVM或环境中重建。2.deserialization反序列化Java反序列化是指将序列化后的字节流重新转换为Java对象的过程恢复对象原有的状态和数据。反序列化通过读取字节流并重建对象的内存结构来实现。二序列化以及反序列化的应用对象持久化保存到文件网络传输RPC、Socket缓存Redis 存储对象消息队列RabbitMQ、RocketMQ 传输对象分布式 Session 共享Java序列化的优点便于对象持久化可以将对象保存到文件或数据库。支持网络传输方便对象在不同系统之间传递。适用于分布式系统实现远程调用、Session 共享等。实现简单对象实现Serializable接口即可进行序列化。三序列化与反序列化的实现1.向文件中写入字符串序列化操作首先是创建这个字节输出流来指向你所要操作的文件然后创建OutputStreamWriter将字节流转换为字符流并按照utf-8的字符集进行写入然后再加一个BufferWriter来增加一个缓冲区来增加写入效率使用这个write方法进行写入字符串然后调用flush方法强制将缓冲区中的数据立即写入文件最后使用close方法关闭流并且释放资源。Test public void test_out_serialization() { try { FileOutputStream fileOutputStream new FileOutputStream(D:\\Java\\Java-demo\\src\\test\\resources\\Student1.txt); OutputStreamWriter outputStreamWriternew OutputStreamWriter(fileOutputStream,StandardCharsets.UTF_8); BufferedWriter bufferedWriternew BufferedWriter(outputStreamWriter); bufferedWriter.write(hello world1); bufferedWriter.flush(); bufferedWriter.close(); }catch (IOException e){ System.out.println(e.getMessage()); } System.out.println(ok); }写入后的效果反序列化操作首先是创建这个字节输入流来指向你所要操作的文件然后创建InputStreamReader将字节流转换为字符流并按照utf-8的字符集进行写入然后再加一个BufferReader来增加一个缓冲区来增加读取效率使用这个readLine方法进行读取一行字符串最后使用close方法关闭流并且释放资源。Test public void test_in_serialization() { try { FileInputStream fileInputStream new FileInputStream(D:\\Java\\Java-demo\\src\\test\\resources\\Student1.txt); InputStreamReader inputStreamReader new InputStreamReader(fileInputStream,StandardCharsets.UTF_8); BufferedReader bufferedReadernew BufferedReader(inputStreamReader); String read bufferedReader.readLine(); bufferedReader.close(); System.out.println(read); }catch (IOException e){ System.out.println(e.getMessage()); } System.out.println(ok); }读取后的效果2.向文件中写入对象首先要创建一个实体类然后这个类要实现Serializable接口package com.cat.entity; import java.io.Serializable; public class Student implements Serializable { //私有化成员变量 private String name; private char sex; private int year; private double gpa; public Student(){ //无参构造 } public Student(String name,char sex,int year,double gpa){ //参数给属性赋值 this.name name; this.sex sex; this.year year; this.gpa gpa; } //重写set和get public String getName() { return name; } public void setName(String name) { this.name name; } public char getSex() { return sex; } public void setSex(char sex) { this.sex sex; } public int getYear() { return year; } public void setYear(int year) { this.year year; } public double getGpa() { return gpa; } public void setGpa(double gpa) { this.gpa gpa; } Override public String toString() { return Student{ name name \ , sex sex , year year , gpa gpa }; } }序列化操作首先是创建一个实体类对象然后再创建这个字节输出流来指向你所要操作的文件然后再创建一个ObjectOutputStream对象输出流将Java对象转换为字节流使用这个writeObject方法进行写入对象然后调用flush方法强制将缓冲区中的数据立即写入文件最后使用close方法关闭流并且释放资源。Test public void test_out_object_serialization() throws IOException { Student studentnew Student(cat,M,21,3.6); File file new File(D:\\Java\\Java-demo\\src\\test\\resources\\Student1.txt); if (file.exists()){ System.out.println(文件存在); }else { file.createNewFile(); } try { FileOutputStream fosnew FileOutputStream(file); ObjectOutputStream oosnew ObjectOutputStream(fos); oos.writeObject(student); oos.flush(); fos.close(); oos.close(); }catch (IOException e){ System.out.println(e.getMessage()); } System.out.println(ok); }写入后的效果从这里可以看出序列化的内容是很难读取的是要靠反序列化进行读取的反序列化操作首先创建这个字节输入流来指向你所要操作的文件然后再创建一个ObjectInputStream对象输入流将字节流转换为Java对象使用这个readObject方法进行写入对象然后调用flush方法强制将缓冲区中的数据立即写入文件最后使用close方法关闭流并且释放资源。Test public void test_in_object_serialization() throws IOException { File file new File(D:\\Java\\Java-demo\\src\\test\\resources\\Student1.txt); if (file.exists()){ System.out.println(文件存在); }else { file.createNewFile(); } try { FileInputStream fisnew FileInputStream(file); ObjectInputStream oisnew ObjectInputStream(fis); Student student (Student) ois.readObject(); System.out.println(student); ois.close(); fis.close(); }catch (ClassNotFoundException e) { throw new RuntimeException(e); } System.out.println(ok); }结果如下四transient关键字被transient关键字修饰的属性不能被序列化这里给sex属性加了transient关键字这里要注意序列化的实体类发生了改变要将文件中的内容删除重新序列化一遍这个实体类才可以要不然反序列化时会报错可以看到这时sex字段的值变为空值没有被序列化五Externalizable接口实现序列化与反序列化Externalizable接口继承Serializable接口实现Externalizable接口需要实现readExternal()方法和writeExternal()方法这两个方法是抽象方法对应的是serializable接口的readObject()方法和writeObject()方法可以理解为把serializable的两个方法抽象出来。Externalizable没有serializable的限制static和transient关键字修饰的属性也能进行序列化。在实体类中重写这两个方法Override //对抽象方法进行重写 public void writeExternal(ObjectOutput out) throws IOException{ out.writeObject(name); out.writeObject(sex); out.writeObject(year); out.writeObject(gpa); } Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name (String) in.readObject(); sex (char) in.readObject(); year (int) in.readObject(); gpa (double) in.readObject(); }相应的测试方法里面调用这两种方法的时候直接调用writeObject()方法和readObject()方法即可重写的writeExternal()和readExternal()方法会自动执行。FileOutputStream fos1 new FileOutputStream(file1); ObjectOutputStream oos1 new ObjectOutputStream(fos1); //调用 ObjectOutputStream 中的 writeObject() 方法 写对象 oos1.writeObject(st); //会自动执行重写的writeExternal()方法FileInputStream fis1 new FileInputStream(file1); //创建对象输入流 ObjectInputStream ois1 new ObjectInputStream(fis1); //读取对象 //会自动执行readExternal()方法 Student1 st1 (Student1) ois1.readObject(); //会抛出异常类找不到异常虽然student类里的sex属性被static或transient修饰但依旧被序列化结果如下文件存在 name cat sex M year 20 gpa 3.6