首先明确一点:默认的序列化方法速度很慢,因为需要对整个对象和他的类都进行保存,因此我们建议自定义序列化格式。

用途 ObjectInputStream ObjectOutputStream
整数 readInt() writeInt(int)
浮点数 readDouble() writeDouble(double)
字符串 readUTF() writeUTF(String)
字节数组 read(byte[] buf, int off,int length) write(byte[])
对象 readObject() writeObject(Object)

哪些数据不会被序列化

  1. 被标记为 transient 的域。
  2. 静态变量。

查看某个类的SerialVersionUID

如果类A实现了Serializable接口,则可以使用Java 提供的serialver命令: serialver  A 。

SerialVersionUID变量的作用

场景:你在公司开发一个类(记为LogManager,用来管理日志,拥有变量Date date,String description,我们使用序列化保存日志信息),并且已经上线使用(已经积累了一些数据),随着时间的推移,你发现你这个类设计的不够完善,因此你需要添加一个实例变量 int errorID,那么你如果按照一般反序列化方法(readObject),则会抛出:InvalidClassException。那么怎么能够成功将原始的数据转换成新版本的LogManager对象呢?

解决:

  1. 使用 Java 提供的serialver命令: serialver  LogManager 计算出原始LogManager的 serialVersionUID(比如为123L)。
  2. 在新版本的LogManager中添加:  static final long serialVersionUID = 123L;

目的:保持不同版本类的序列化的兼容性

序列化类A(类A继承自类B),但是类B不可序列化,怎么办?

默认情况:

  1. 先将类A的实例变量全部还原。
  2. 因为类A继承类B,因此类A的对象也会有类B的实例变量,对于类B的实例变量,调用类B的默认无参构造函数初始化类B的实例变量。(一定要定义超类无参构造函数,不然会抛 no valid constructor)

解决:自定义readObject和writeObject。

对序列化的数据加密

问题:我们知道,序列化主要用于数据传输,但是序列化的数据是可以反序列化的,因此黑客可以直接把你的数据截下来(比如你的序列化文件为data.txt,用WinHeX打开后,基本就能看到所涉及的类和你传输的数据)。那么怎么样能够加密序列化的数据呢?
解决:通过自定义的序列化方法(在要序列化的对象中实现readObject和writeObject方法)。

  • private void writeObject(ObjectOutputStream os)throws IOException    // 你如果重写时必须是private的。
  • private void readObject(ObjectInputStream is)throws IOException,ClassNotFoundException   //你如果重写时必须是private的
 1 import java.io.*;
 2 public class Serialize05
 3 {
 4     public static void main(String[] args) throws Exception{
 5         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.txt"));
 6         out.writeObject(new Person("admin","abc123"));
 7         out.close();
 8         ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.txt"));
 9         Person person = (Person)in.readObject();
10         System.out.println(person);    
11     }
12 }
13 class Person implements Serializable
14 {
15     String name;
16     String password;
17     public Person(String name,String password)
18     {
19         this.name = name;
20         this.password = password;
21     }
22     private void writeObject(ObjectOutputStream os)throws IOException
23     {
24         os.writeUTF(name);
25         byte[] pass = password.getBytes("UTF-8");
26         for(int i=0;i<pass.length;i++)
27         {
28             pass[i] = (byte)(pass[i] ^ 32);        //对密码加密
29         }
30         os.write(pass);
31     }
32     private void readObject(ObjectInputStream is)throws IOException,ClassNotFoundException
33     {
34         name = is.readUTF();
35         byte[] pass = new byte[1024];
36         int size = is.read(pass,0,1024);
37         for(int i=0;i<pass.length;i++)
38         {
39             pass[i] = (byte)(pass[i] ^ 32);        //对密码解密
40         }
41         String password = new String(pass,0,size,"UTF-8");
42         this.password = password;
43     }
44     public String toString()
45     {
46         return "name="+name+",password="+password;
47     }
48 }
View Code

相关文章:

  • 2021-09-02
  • 2022-12-23
  • 2021-06-21
  • 2022-12-23
  • 2021-07-28
  • 2021-06-20
  • 2021-04-26
猜你喜欢
  • 2022-12-23
  • 2022-03-05
  • 2022-12-23
  • 2021-06-29
  • 2022-02-09
  • 2021-11-03
相关资源
相似解决方案