今天在看JDK的一些源码的时候,发现有一个关键字transient自己没怎么玩过。所以这里写此博客来整理下这个关键字的用法。
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
翻找资料的时候,有一篇不错的博客,原文地址:http://www.cnblogs.com/dolphin0520/p/3933551.html。感谢作者的无私分享。
首先我们先写一段代码来序列化和反序列化一个Java对象:
package test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @创建作者: LinkinPark * @创建时间: 2016年1月6日 * * @功能描述:序列化和反序列化一个对象 */ public class Test7 { private static final String filePath = "/Users/LinkinPark/Desktop/linkin.txt"; public static void main(String[] args) { User user = new User().setUserName("LinkinPark").setPassWord("Binger1214"); // 序列化一个对象 try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath))) { os.writeObject(user); System.out.println(user.toString()); } catch (IOException e) { e.printStackTrace(); } // 反序列化一个对象 try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath))) { User userByRead = (User) in.readObject(); System.out.println(userByRead.toString()); } catch (Exception e) { e.printStackTrace(); } } } class User implements Serializable { private String userName;// 用户姓名 private String passWord;// 密码 public String getUserName() { return userName; } public User setUserName(String userName) { this.userName = userName; return this; } public String getPassWord() { return passWord; } public User setPassWord(String passWord) { this.passWord = passWord; return this; } @Override public String toString() { return "User [userName=" + userName + ", passWord=" + passWord + "]"; } }
OK,现在我们使用这个transient关键字来修饰User对象的密码属性,代码如下:
package test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * @创建作者: LinkinPark * @创建时间: 2016年1月6日 * * @功能描述:transient关键字使用 */ public class Test7 { private static final String filePath = "/Users/LinkinPark/Desktop/linkin.txt"; public static void main(String[] args) { User user = new User().setUserName("LinkinPark").setPassWord("Binger1214"); // 序列化一个对象 try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath))) { os.writeObject(user); System.out.println(user.toString()); } catch (IOException e) { e.printStackTrace(); } // 反序列化一个对象 try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath))) { User userByRead = (User) in.readObject(); System.out.println(userByRead.toString()); } catch (Exception e) { e.printStackTrace(); } } } class User implements Serializable { private String userName;// 用户姓名 private transient String passWord;// 密码 public String getUserName() { return userName; } public User setUserName(String userName) { this.userName = userName; return this; } public String getPassWord() { return passWord; } public User setPassWord(String passWord) { this.passWord = passWord; return this; } @Override public String toString() { return "User [userName=" + userName + ", passWord=" + passWord + "]"; } }
对比2次控制台的输出,我们发现java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
再明显一点我们打开2次序列化后的linkin.txt文件,发现第2次明显的没有将密码这个字段序列化到文件中。通过上面的实践,这里来总结下transient关键字的用法:
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。关于这点就不做多的解释了,类变量属于类的属性,存在于JVM内存中的,不能被序列化。