我们知道在java中,我们要将一个对象序列化以后,再将其反序列化以后就可以得到之前序列化之前的内容.但是,假如我们有时并不是想让某个类的所有的成员变量都要被序列化,那怎么办呢?其中一种方法是使用静态static
来修饰,另外一种就是今天要说的transient
这个关键字.
transient关键字能实现什么?
当对象被序列化时(写入字节序列到目标文件)时,transient阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行,这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为java.io.InputStream
的变量,序列化时这些变量引用的输入流无法被打开。-
如何使用transient?
下面是一个小小的例子来简要说明一下,就直接上代码了:package com.rain.trainsent; 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; import java.util.ArrayList; public class TestTransient { public static void main(String[] args) throws FileNotFoundException, IOException { // TODO Auto-generated method stub Student s = new Student("zhangsan",12); System.out.println(s.toString()); //序列化 被设置为transient 没有被序列化进去 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("student.txt")); o.writeObject(s); o.close(); //重新读取序列化的内容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt")); try { Student stu = (Student) in.readObject(); System.out.println(stu.toString()); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Student implements Serializable{ private transient String name; private int id; public Student(String name, int id) { super(); this.name = name; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Student [name=" + name + ", id=" + id + "]"; } }
可以看到,当我们将这个类的name属性用transient修饰后,当我们将其序列化以后,反序列化的时候就得不到它之前的值了
-
transient使用细节——被transient关键字修饰的变量真的不能被序列化吗?
看一下下面的一个例子:package com.rain.test; import java.io.Externalizable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class TestTransient implements Externalizable { private transient String content="我会被序列化的,不管我有没有被transient修饰"; public static void main(String[] args) throws ClassNotFoundException, IOException { TestTransient et = new TestTransient(); ObjectOutput out = new ObjectOutputStream(new FileOutputStream( new File("test"))); out.writeObject(et); ObjectInput in = new ObjectInputStream(new FileInputStream(new File( "test"))); et = (TestTransient) in.readObject(); System.out.println(et.content); out.close(); in.close(); } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(content); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { content = (String) in.readObject(); } }
我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是
Serializable
接口,则所有的序列化将会自动进行,若实现的是Externalizable
接口,则没有任何东西可以自动序列化,需要在writeExternal
方法中进行手工指定所要序列化的变量,这与是否被transient
修饰无关.因此第二个例子输出的是变量content初始化的内容,而不是null.以上是个人对关键字transient的一些理解,希望能起到抛砖引玉的作用.