引用链接:https://blog.csdn.net/u010188178/article/details/83581506
百度百科的解释:
Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。
作用:
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
接下来我们就通过写一个自定义的类及其测试方法来进行测试。
ublic static void main(String[] args) throws IOException {
test();
}
public static class TransientTest implements Serializable{
private static final long serialVersionUID = 233858934995755239L;
private String name1;
private transient String name2;
public TransientTest(String name1,String name2){
this.name1 = name1;
this.name2 = name2;
}
public String toString() {
return String.format("TransientTest.toString(): name1=%s,name2=%s", name1, name2);
}
}
public static void test() {
String name1="常规属性",name2="transient修饰的属性";
TransientTest test = new TransientTest(name1, name2);
System.out.println("序列化前:"+test.toString());
ObjectOutputStream objectOutputStream;
ObjectInputStream objectInputStream;
String filePath = "D:/Java/Project/TransientTest.obj";
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
objectOutputStream.writeObject(test);
objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
TransientTest readObject = (TransientTest) objectInputStream.readObject();
System.out.println("序列化后:" + readObject.toString());
}catch (IOException e) {
e.printStackTrace();
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
知识兔运行之后得到的结果为:
从这个结果我们就可以看出transient关键字修饰的变量不参与序列化。
在查看JDK源码的时候会发现很多地方都会加上transient关键字来修饰一些属性,那究竟是出于什么考虑才这么做呢?
我觉得,应该是为了节约磁盘空间,避免造成不必要的浪费吧。
以ArrayList中的 transient Object[] elementData 为例,这个成员变量的注释为:
翻译出来就是:
/ * *
*存储ArrayList元素的数组缓冲区。
* ArrayList的容量是这个数组缓冲区的长度。任何
*带有elementData的空ArrayList == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
*当添加第一个元素时,将被扩展到DEFAULT_CAPACITY。
* /
这个缓冲区的容量实际上并不是ArrayList的容量,因为其实际上会预留一些空间,当空间不足时还会扩容,为减少浪费,因此在序列化时不会按照默认算法将这个成员变量写入磁盘。而是写了个writeObject方法,序列化时会调用这个方法将其持久化,在反序列化是,调用readObject,将其恢复出来。
这2个方法为:
参照上面发两个方法,对TransientTest进行修改:
ublic static class TransientTest implements Serializable{
private static final long serialVersionUID = 233858934995755239L;
private String name1;
private transient String name2;
public TransientTest(String name1,String name2){
this.name1 = name1;
this.name2 = name2;
}
public String toString() {
return String.format("TransientTest.toString(): name1=%s,name2=%s", name1, name2);
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
s.defaultWriteObject();
s.writeObject(name2);
}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
name2=String.valueOf(s.readObject());
}
}
知识兔
结果发生了改变: