之前在研究java中ArrayList源码。在ArrayList的域中有 transient Object[] elementData (Object类型的数组elementData被transient修饰)。此处黑人问号?关键字transient是啥?
1.在此之前我们需要了解一下什么是序列化和反序列化
把对象转换为字节序列的过程称为对象的序列化
把字节序列恢复为对象的过程称为对象的反序列化
下面举一个简单的例子帮助大家理解:
比如在一个学生类的ArrayList中,其中有一个 name = ‘Bob’,现在我们把name ‘Bob’改成’Bill’。但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的’Bill’存储到磁盘上,下次重新运行程序,变量又被初始化为’Bob’。不过好在ArrayList是可序列化的。
2.关键字transient(临时的)(用来表示一个域不是该对象序行化的一部分)
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)一个静态变量不管是否被transient修饰,均不能被序列化。
3)transient关键字修饰范围,只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
举例
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("Alexia");
user.setPasswd("123456");
System.out.println("read before Serializable: ");
System.out.println("username: " + user.getUsername());
System.err.println("password: " + user.getPasswd());
try {
ObjectOutputStream os = new ObjectOutputStream(
new FileOutputStream("D:/user.txt"));
os.writeObject(user); // 将User对象写进文件
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
// 在反序列化之前改变username的值
User.username = "jmwang";
ObjectInputStream is = new ObjectInputStream(new FileInputStream(
"D:/user.txt"));
user = (User) is.readObject(); // 从流中读取User的数据
is.close();
System.out.println("\nread after Serializable: ");
System.out.println("username: " + user.getUsername());
System.err.println("password: " + user.getPasswd());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class User implements Serializable {
private static final long serialVersionUID = 8294180014912103005L;
public static String username;
private transient String passwd;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
这时我们发现结果如图所示:
密码字段为null,说明反序列化时根本没有从文件中获取到信息。密码从开始就没有参与序列化。