java对象序列化与反序列化
1. 目的:在开发中有时候为了考虑到访问量,所以需要优化代码,可以减少对数据库的访问,比如可以将一些不常改变的数据通过序列化的方式保存在一个文件中,然后用户再次访问的时候可以通过反序列化的方式 从文件中读取。
2. 二进制文件,后缀为.dat、.bat、.obj、.exe、.com,一般指机器编译过的文件。
3. 写入序列化数据到文件中,主要是两个对象:FileOutputStream对象、ObjectOutputStream对象(负责向指定流中写入序列化的对象)
4. 从文件中读取序列化数据,主要是两个对象:FileInputStream对象、ObjectInputStream对象(负责从指定流中读取序列化数据并还原成序列化对象)
5. 序列化的读写顺序是先进先出,先写入的先读出,后写入的后读出。
6. 序列化一个对象要实现java.io.Serializable接口,对于不想序列化的数据:
7 . 不能序列化的数据:(1)对象属性为“瞬间态”(关键字声明transient);(2)静态字段;
8. 序列化父类子类问题:若只有子类继承了Serializable接口,而父类不继承,那么结果出来为父类的某个变量。
一、java对象序列化为二进制
写入文件:
List dataList = new ArrayList();
dataList.add(“abc”);
dataList.add(“123”);
String FilePath = “e:/data.dat”;
FileOutputStream fos = new FileOutputStream(FilePath);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(dataList);
二、二进制反序列化为java对象
读取文件:
try{
FileInputStreamfis = new FileInputStream(FilePath);
ObjectInputStreamois = new ObjectInputStream(fis);
Listresult = (List) ois.readObject();
System.out.println(result); //输出为[abc, 123] (序列化结果)
}catch(Exception e){
e.printStackTrace();
}finally{
if(fis != null){ fis.close(); }
if(ois != null){ois.close(); }
}
三、实例
创建一个类,必须实现Serializable接口。
public class User implements Serializable{ private static final long serialVersionUID = 1L; private Integer id; private String name; private String sex; private String age; private Country country; @SuppressWarnings("unused") private User() { super(); } //getXXX()和setXXX()方法 } public class Country implements Serializable{ private String id; private String countryName; private String where; //getXXX()和setXXX()方法 } public class TestSerialization { public static void main(String[] args) { outputObject(); inputObject(); } private static void inputObject(){ try { FileInputStream input = new FileInputStream("d:"+File.separator+"use.out"); ObjectInputStream objInput = new ObjectInputStream(input); Object user = (Object) objInput.readObject(); System.out.println(user.toString()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void outputObject() { FileOutputStream os; try { os = new FileOutputStream("d:"+File.separator+"use.out"); ObjectOutputStream o = new ObjectOutputStream(os); Country coun = new Country("2","中国","east"); Object user = new User(1, "zhangsan", "男","12",coun); o.writeObject(user); o.flush(); } catch (Exception e) { e.printStackTrace(); } } }
这样可以将对象序列化为一个文件,也可以将文件反序列化为对象。
四、注意的问题
1.序列化ID问题:两个客户端AB通过网络socket传递数据,A端将对象C序列化为二进制数据再给B,B反序列化得到C。但总提示反序列化不成功。
关键:JVM是否允许反序列化。这不仅决定于类路径、功能代码是否一致,更决定于两个类序列化ID是否一致。
2.序列化父类子类问题:若只有子类继承Serializable接口而父类不继承,则结果出来的是父类某变量的。