Java序列化总结(最全)
概念
- 实现 Serializable 接口, 它只是一个标记接口,不实现也能够进行序列化
- RMI: 远程方法调用
- RPC: 远程过程调用
序列化ID
解决了序列化与反序列出现代码不一致的问题, 不一致将导致序列化失败 private static final long serialVersionUID = 1L; // 便于进行代码版本控制private static final long serialVersionUID = -5453781658505116230L; //便于控制代码结构
静态变量序列化
- x*- 序列化的是对象,而不是类,静态变量属于类级别,所以序列化不会保存静态变量
父类序列化与Trancient关键字
- 一个子类实现了 Serializable 接口,它的父类没有实现 Serializable 接口,那么序列化子类时,父类的值都不会进行保存
- 需要父类保存值 ,就需要让父类也实现Serializable 接口
- 取父对象的变量值时,它的值是调用父类无参构造函数后的值,出现如 int 型的默认是 0,string 型的默认是 null, 要指定值,那么需要在父类构造方法中进行指定
- Trancient关键字指定的内容将不会被保存(阻止序列化)
- 在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 nul
- 使用继承关系同样可以实现,Trancient一样的效果,,即为父类不需要实现Serializable接口
利用PutField getPutField字段进行加密
原理:
- 1: 进行序列化时,JVM试图调用对象的writeObject() readObject() 方法(允许自己私有化实现)
- 2:默认调用是 ObjectOutputStream 的 defaultWriteObject 方法以及 ObjectInputStream 的 defaultReadObject 方法
private void writeObject(ObjectOutputStream out) { try { PutField putFields = out.putFields(); //放到 System.out.println("原密码:" + password); password = "encryption";// 模拟加密 putFields.put("password", password); System.out.println("加密后的密码" + password); out.writeFields(); } catch (IOException e) { e.printStackTrace(); } } private void readObject(ObjectInputStream in) { try { GetField readFields = in.readFields(); Object object = readFields.get("password", ""); System.out.println("要解密的字符串:" + object.toString()); password = "pass";// 模拟解密,需要获得本地的密钥 } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 调用的时候直接调用 out的writeObject(),或者in的readObject() 即可
序列化存储规则
- 对同一对象两次写入文件, 第一次写入实际对象的序列化后的数据,第二次写入同一个对象的引用数据.(即为指向同一个对象)
- 1: 节约了磁盘存储空间
- 2: 反序列化后的数据的值,应该是第一次保存的数据的值,(对于同一个对象第二次序列化,值是不会进行保存的)