简介
当一个类的对象需要被序列化时,但是某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient 修饰。
只要被关键字transient 修饰了,序列化时这个属性就不会被序列化了。同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。
代码
Person 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package cn.vgbhfive;
import java.io.Serializable;
/** * @auther Vgbh * */
public class Person implements Serializable{
/** * */ private static final long serialVersionUID = 1L;
private Integer id; private transient String name; private String firstName;
public Person(Integer id, String name, String firstName) { this.id = id; this.name = name; this.firstName = firstName; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", firstName=" + firstName + "]"; }
public static void main(String[] args) { Person p1 = new Person(12, "ssss", "ddd"); SerializationUtils.writeObject(p1); Person p2 = (Person) SerializationUtils.readObject(); System.out.println(p2.toString()); }
}
|
SerializationUtils 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| package cn.vgbhfive;
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable;
/** * @auther Vgbh * */
public class SerializationUtils {
private static final String FILENAME = "F:/obj.bin"; /** * 序列化 * @param s */ public static void writeObject(Serializable s) { try { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(FILENAME)); out.writeObject(s); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 反序列化 * @return */ public static Object readObject() { Object obj = null; try { ObjectInputStream in = new ObjectInputStream(new FileInputStream(FILENAME)); try { obj = in.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } in.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return obj; } }
|
执行结果
![](https://i.loli.net/2019/05/20/5ce2caff3191567901.jpg)
从执行结果就可以看出,瞬态变量没有被序列化,因此在反序列化时,name 的值为null 。
注意
下面这些是在实际编码过程中,可能会遇到的问题的解决方法,希望会对你有用。
- 显式声明UID
在序列化和反序列化的类不一致的情形下,反序列化回报一个InvalidClassException 异常,原因就是序列化和反序列化所对应的类版本发生了变化。
- 避免用序列化类在构造函数中为不变量赋值
反序列化时构造函数不会执行。
- 避免为final变量复杂赋值
这里的赋值指的是“简单对象”,简单对象包括:8个基本类型、数组、字符串。
- 使用序列化类的私有方法巧妙解决部分属性持久化问题
实现了Serialization 接口的类可以实现两个私有方法:writeObject() 和readObject() ,以影响和控制序列化和反序列化的过程。
- 反序列化时以下情况不会被重新赋值:通过构造函数为final 变量赋值、通过方法返回值为final 变量赋值、final 修饰的属性不是基本类型。