- 在类实现序列化接口,而类下某个变量不想被序列化的情况下,用transient修饰该变量,可避免该变量被序列化。
2.transient的使用
在Java中,对象的序列化可以通过两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手动指定所要序列化的变量,这与是否被transient修饰无关。
实现Serializable接口示例:

public class Test { public static void main(String[] args) throws Exception { User user = new User("test", "123456"); System.out.println("写入文件前:name="+user.getName()+" password="+user.getPassword()); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/Desktop/user.txt")); out.writeObject(user); out.flush(); out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/Desktop/user.txt")); User u = (User)in.readObject(); in.close(); System.out.println("重新读取后:name="+u.getName()+" password="+u.getPassword()); } } class User implements Serializable{ private static final long serialVersionUID = 1L; private String name; private transient String password; public User(String name,String password){ this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
运行结果
写入文件前:name=test password=123456
重新读取后:name=test password=null
通过上面的示例我们可以看出以下几点:
- 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
- transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
- 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
实现Externalizable接口示例:

public class Test { public static void main(String[] args) throws Exception { User user = new User("test", "123456"); System.out.println("写入文件前:name="+user.getName()+" password="+user.getPassword()); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/Desktop/user.txt")); out.writeObject(user); out.flush(); out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/Desktop/user.txt")); User u = (User)in.readObject(); in.close(); System.out.println("重新读取后:name="+u.getName()+" password="+u.getPassword()); } } class User implements Externalizable{ private String name; private String password; public User(){} public User(String name,String password){ this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(name); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { name = (String)in.readObject(); } }
运行结果
写入文件前:name=test password=123456
重新读取后:name=test password=null
通过上面的示例我们可以看出,在Exteralizable接口实现类中完全不一样,被transient修饰的属性,在exteralWrite中被写入,就能被序列化。
3.总结
transient使用总结:
- 修饰符transient可以应用于类的字段成员,以关闭这些字段成员的序列化。
- 你可以在需要对现有状态字段进行保护或计算的字段的类中使用transient修饰符。当序列化那些字段(如日志记录器和线程)毫无意义时,可以使用它。
- 序列化不关心访问修饰符,如private。所有非transient字段都被认为是对象持久状态的一部分,并且都符合持久状态的条件(实现Serializable接口的情况下)。
- 无论何时将任何final字段、引用计算为常量表达式,JVM都会对其进行序列化,忽略transient修饰符的存在。
- HashMap类是java中transient修饰符的一个很好的用例。