对象在文件的存取操作有两种流,ObjectInputStream & ObjectOutputStream ,说到对文件操作,肯定少不了文件字节流 ,FileInputstream & FileOutputStream ,对象流内置字节流,然后通过字节方式,传输对象。
ObjectInputStream 有 readObject( ) 从文件中读出一个对象
ObjectOutputStream 有 writeObject( ) 向文件写入一个对象
类定义:
import java.io.Serializable;
public class User implements Serializable{//实现序列化接口
/**
* 序列化版本,辨别这个类的标志
*/
private static final long serialVersionUID = -7829726230920543458L;
private String username;
public User() {
}
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "User [username=" + username + "]";
}
}
具体实现:
@Test
public void TestObject() throws Exception{
File f =new File("user.txt");
User user = new User("大飞哥");
try(
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
){
oos.writeObject(user); //把user对象写入
User us = (User) ois.readObject();//从文件中读取user
System.out.println(us.toString());//输出
}
}
结果:
看控制台可以知道我们已经成功存取了一个对象。
实现序列化接口是对象输入输出到文件必要的途径。那么那个private static final long serialVersionUID = -7829726230920543458L;
有什么用呢,这个是识别是否为该类的编号。当多个类的对象存入文件或该类的方法和属性有改变时,文件内的对象属于该类的凭证。当我们不添加序列化编号时,jvm会自动添加一个随机的编号。当类有更变时,如删除重写的toString()方法,jvm无法辨别是否还是该类,又会因为序列化编号不匹配(jvm前后生成序列号随机),会有异常抛出,如:
Exception in thread "main" java.io.InvalidClassException: Test.User; local class incompatible: stream classdesc serialVersionUID = -7829726230920543458, local class serialVersionUID = 6005621513812223924 |
所以我们在实现序列化接口时就应该添加序列化编号
添加了确定的序列化,从文件中读取的对象就可以使用新添加的方法和属性。
现在删除我们重写的toString方法(),看看可不可以正常使用呢。
结果当然是ok:
如果我们不想让某些数据被记录进去该怎么办呢,我们可以添加transient关键字声明。
我们现在给username添加关键字,具体实现:
private transient String username;
其他代码不变,结果:
那么我们可不可以把 多个对象的集合ArrayList对象存进去呢,答案时可以的。
具体实现:
@Test
public void TestObject() throws Exception{
File f =new File("user.txt");
User user = new User("大飞哥");
User user2 = new User("小飞哥");
List<User> list = new ArrayList<User>();
list.add(user);
list.add(user2);
try( ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
){
oos.writeObject(list);
List<User> l=(List<User>)ois.readObject();//类型转化的警告
for (int i = 0; i < l.size(); i++) {//输出所有信息
System.out.println(l.get(i).toString());
}
}
}
结果:
成功了,当然千万不要忘记加泛型哦,标明类型是种好习惯,也是让java虚拟机知道这是储存什么类型到数据,后面使用就不用强制转换。<完>