transient:
adj. 转瞬即逝的,短暂的;暂住的,(工作)临时的
n. 暂住者,流动人口;(电流、电压、频率的)瞬变
transient 的作用和使用方法:
我们知道对象实现了 serilizable 就可以被序列化,我们不必关系具体序列化的过程,只要实现了这个接口,这个类的所有属性和方法都会自动的序列化
在实际的开发过程中,为了安全起见,通常我们并不希望所有的属性都被序列化在网络操作中传输,那么此时我们只需要在 不希望序列化的属性前,添加 transient 关键字即可。
1. 需要实现 serilizible 接口
2. 在不希望被序列化的属性前,添加 transient 关键字。
示例CODE
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TransientDemo {
public static void main(String[] args) {
User user = new User();
user.setUsername("wddong");
user.setPassword("123456");
System.out.println("read before Serializable: "+ user);
try {
ObjectOutputStream os = new ObjectOutputStream(
new FileOutputStream("E:/temp/user.txt"));
os.writeObject(user); // 将User对象写进文件
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
ObjectInputStream is = new ObjectInputStream(new FileInputStream(
"E:/temp/user.txt"));
user = (User) is.readObject(); // 从流中读取User的数据
is.close();
System.out.println("\nread after Serializable: "+ user);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Data
class User implements Serializable {
private static final long serialVersionUID = 8294180014912103005L;
private String username;
private transient String password;
}
程序输出:
read before Serializable: : User(username=wddong, password=12345)
read after Serializable: : User(username=wddong, password=null)
密码字段为null,可以看出反序列化没有从文件中获取到信息。
小结:
- 变量一旦被 transient 修饰,变量将不再会是持久化的一部分。
- transient 关键字只能够修饰变量,不能够用来修饰方法和类。
- transient 修饰的变量不能被持久化,而 static 修饰的变量不论有没有被 transient 修饰,都不能被序列化。
为什么被 static 修饰的变量不论是否被transient ,不能被序列化??
还是以上的示例,改造一下。(static 型变量为当前JVM中对应的static 变量的值)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TransientTest {
public static void main(String[] args) {
User user = new User();
user.setUsername("wddong");
user.setPasswd("123456");
System.out.println("read before Serializable: "+user);
try {
ObjectOutputStream os = new ObjectOutputStream(
new FileOutputStream("E:/temp/user.txt"));
os.writeObject(user); // 将User对象写进文件
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
// 在反序列化之前改变username的值
User.username = "jmwang";
ObjectInputStream is = new ObjectInputStream(new FileInputStream(
"E:/temp/user.txt"));
user = (User) is.readObject(); // 从流中读取User的数据
is.close();
System.out.println("\nread after Serializable: " + user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Data
class User implements Serializable {
private static final long serialVersionUID = 8294180014912103005L;
public static String username;
private transient String passwd;
}
程序输出:
read before Serializable: : User(username=wddong, password=12345)
read after Serializable: : User(username=jmwang, password=null)
== 这说明反序列化后类中static型变量username的值为当前JVM中对应static变量的值,为修改后jmwang,而不是序列化时的值wddong。==
被 transient 修饰的变量是否一定不能被序列化??
不是,transient 和 serilizible 配合使用,被修饰的变量不能被序列化,serilizible 接口是自动序列化接口,继承了这个接口的类会被自动的序列化,除了 serilizible 接口,还有Externalizable 接口。若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。