1,用途
当一个对象实现了Serilizable接口,这个对象就可以被序列化。而有时候我们可能要求:当对象被序列化时(写入字节序列到目标文件)时,有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
所以,transient的用途在于:阻止实例中那些用此关键字声明的变量持久化。
2,使用方法
序列化的时候,将不需要序列化的属性前添加关键字transient即可。
示例:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class UserInfo implements Serializable { private static final long serialVersionUID = 996890129747019948L; private String name; private transient String psw; public UserInfo(String name, String psw) { this.name = name; this.psw = psw; } public String toString() { return "name=" + name + ", psw=" + psw; } } public class TestTransient { public static void main(String[] args) { UserInfo userInfo = new UserInfo("张三", "123456"); System.out.println(userInfo); try { // 序列化,被设置为transient的属性没有被序列化 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt")); o.writeObject(userInfo); o.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } try { // 重新读取内容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt")); UserInfo readUserInfo = (UserInfo) in.readObject(); //读取后psw的内容为null System.out.println(readUserInfo.toString()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
运行结果:
1 name=张三, psw=123456 2 name=张三, psw=null
密码字段为null,说明被标记为transient的属性在对象被序列化的时候不会被保存。
使用小结:
1,一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2,transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
对于第三点,加上static之后,依然能把姓名输出。这是因为:反序列化后类中static型变量name的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。下例可说明,其值时JVM中得到的而不是反序列化得到的:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class UserInfo implements Serializable { private static final long serialVersionUID = 996890129747019948L; private static String name; private transient String psw; public UserInfo(String name, String psw) { this.name = name; this.psw = psw; } public static String getName() { return name; } public static void setName(String name) { UserInfo.name = name; } public String getPsw() { return psw; } public void setPsw(String psw) { this.psw = psw; } public String toString() { return "name=" + name + ", psw=" + psw; } } public class TestTransient { public static void main(String[] args) { UserInfo userInfo = new UserInfo("张三", "123456"); System.out.println(userInfo); try { // 序列化,被设置为transient的属性没有被序列化 ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("UserInfo.txt")); o.writeObject(userInfo); o.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } try { //在反序列化之前改变name的值 userInfo.setName("hello"); // 重新读取内容 ObjectInputStream in = new ObjectInputStream(new FileInputStream("UserInfo.txt")); UserInfo readUserInfo = (UserInfo) in.readObject(); //读取后psw的内容为null System.out.println(readUserInfo.toString()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
运行结果:
1 name=张三, psw=123456 2 name=hello, psw=null
这说明反序列化后类中static型变量name的值为当前JVM中对应static变量的值,为修改后hello,而不是序列化时的值“张三”