transient 关键字
认识transient
transient 中文意思是短暂的,临时的。
Java中transient关键字的作用,简单地说,就是让某些被修饰的成员属性变量不被序列化,这一看好像很好理解,就是不被序列化,那么什么情况下,一个对象的某些字段不需要被序列化呢?如果有如下情况,可以考虑使用关键字transient修饰:
1、类中的字段值可以根据其它字段推导出来,如一个长方形类有三个属性:长度、宽度、面积(示例而已,一般不会这样设计),那么在序列化的时候,面积这个属性就没必要被序列化了;
2、其它如密码,看具体业务需求吧,哪些字段不想被序列化;
PS ArrayList、HashMap等源码中也使用transient关键字
/**
* The number of times this HashMap has been structurally modified
* Structural modifications are those that change the number of mappings in
* the HashMap or otherwise modify its internal structure (e.g.,
* rehash). This field is used to make iterators on Collection-views of
* the HashMap fail-fast. (See ConcurrentModificationException).
*/
transient int modCount;
举例
class Rectangle implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1710022455003682613L;
private Integer width;
private Integer height;
private transient Integer area;
public Rectangle (Integer width, Integer height){
this.width = width;
this.height = height;
this.area = width * height;
}
public void setArea(){
this.area = this.width * this.height;
}
@Override
public String toString(){
StringBuffer sb = new StringBuffer(40);
sb.append("width : ");
sb.append(this.width);
sb.append("\nheight : ");
sb.append(this.height);
sb.append("\narea : ");
sb.append(this.area);
return sb.toString();
}
}
public class TransientExample{
public static void main(String args[]) throws Exception {
Rectangle rectangle = new Rectangle(3,4);
System.out.println("1.原始对象\n"+rectangle);
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("rectangle"));
// 往流写入对象
o.writeObject(rectangle);
o.close();
// 从流读取对象
ObjectInputStream in = new ObjectInputStream(new FileInputStream("rectangle"));
Rectangle rectangle1 = (Rectangle)in.readObject();
System.out.println("2.反序列化后的对象\n"+rectangle1);
rectangle1.setArea();
System.out.println("3.恢复成原始对象\n"+rectangle1);
in.close();
}
}
打印结果是
1.原始对象
width : 3
height : 4
area : 12
2.反序列化后的对象
width : 3
height : 4
area : null
3.恢复成原始对象
width : 3
height : 4
area : 12
总结
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
PS:使用Externalizable序列化,不论是否使用transient修饰,都将被序列化。
Externalizable 是 Serializable 的派生类,实现了writeExternal(out)和readExternal(in) ;具体可自己尝试下