序列化Serializable
概念:
序列化:将了自定义的对象保存到介质中(网络、文件etc.)。
反序列化:将介质中的数据读取出来生成对象。
序列化是基于字节流的操作,使用到的流有FileInputStream/FileOutputStream,ObjectInputStream/ObjectOutputStream。
可以进行序列化的内容:完整类名,属性(除用static,transient修饰的属性外),注:方法一定不能被序列化。
Serializable是空接口,标识接口。
实现了Serializable的序列化和反序列化:
User类:
1 package com.wj.serial; 2 3 import java.io.Externalizable; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.io.ObjectInput; 7 import java.io.ObjectInputStream; 8 import java.io.ObjectOutput; 9 import java.io.ObjectOutputStream; 10 import java.io.OutputStream; 11 import java.io.Serializable; 12 13 /** 14 * @param name 15 * @param age 16 * @param subjectString 17 * @author qixiuxuanxi 18 */ 19 @SuppressWarnings("unused") 20 public class User implements Serializable{ 21 // TODO 防止反序列化异常 22 private static final long serialVersionUID = 1L; 23 private String name; 24 private Integer age; 25 private String subjectString; 26 27 public User() { 28 } 29 30 public User(String name, Integer age, String subjectString) { 31 this.name = name; 32 this.age = age; 33 this.subjectString = subjectString; 34 } 35 36 public String getName() { 37 return name; 38 } 39 40 public void setName(String name) { 41 this.name = name; 42 } 43 44 public Integer getAge() { 45 return age; 46 } 47 48 public void setAge(Integer age) { 49 this.age = age; 50 } 51 52 public String getSubjectString() { 53 return subjectString; 54 } 55 56 public void setSubjectString(String subjectString) { 57 this.subjectString = subjectString; 58 } 59 60 @Override 61 public String toString() { 62 return "User [name=" + name + ", age=" + age + ", subjectString=" + subjectString + "]"; 63 }
测试类SerialTest:
1 package com.wj.serial; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.ObjectInputStream; 8 import java.io.ObjectOutputStream; 9 10 public class SerialTest1 { 11 12 public static void main(String[] args) { 13 User user = new User(); 14 user.setAge(1); 15 user.setName("lisi"); 16 user.setSubjectString("建筑"); 17 //序列化 18 writeSerial(user); 19 //反序列化 20 User user2 = readSerial(); 21 System.out.println(user2); 22 23 } 24 25 private static User readSerial() { 26 User user = null; 27 FileInputStream fin = null; 28 ObjectInputStream oin = null; 29 30 try { 31 fin = new FileInputStream("user.dat"); 32 oin = new ObjectInputStream(fin); 33 user = (User) oin.readObject(); 34 } catch (FileNotFoundException e) { 35 e.printStackTrace(); 36 } catch (ClassNotFoundException e) { 37 e.printStackTrace(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } finally { 41 try { 42 oin.close(); 43 fin.close(); 44 } catch (IOException e) { 45 e.printStackTrace(); 46 } 47 } 48 return user; 49 } 50 51 private static void writeSerial(User user) { 52 FileOutputStream fout = null; 53 ObjectOutputStream oout = null; 54 if (user == null) { 55 throw new RuntimeException("对象为空"); 56 } 57 try { 58 fout = new FileOutputStream("user.dat"); 59 oout = new ObjectOutputStream(fout); 60 oout.writeObject(user); 61 } catch (FileNotFoundException e) { 62 e.printStackTrace(); 63 } catch (IOException e) { 64 e.printStackTrace(); 65 } finally { 66 try { 67 oout.close(); 68 fout.close(); 69 } catch (IOException e) { 70 e.printStackTrace(); 71 } 72 } 73 74 } 75 }
个性化的序列化:
1.可以在属性中添加transient关键字,该属性将不会被序列化。
2.在需要序列化的类(即 User类)中将实现Serializable改为实现External并实现其方法,部分代码:
@Override public void writeExternal(ObjectOutput out) throws IOException { out.writeUTF(this.name); out.writeInt(this.age); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { this.name = in.readUTF(); this.age = in.readInt(); }
3.可以自己在需要序列化的类(User)中先继承Serializable再写两个private方法(写出你想序列化的属性就实现了个性化),
如下:
private void writeObject(ObjectOutputStream out) throws IOException{ out.writeUTF(this.name); out.writeInt(this.age); } private void readObject(ObjectInputStream in) throws FileNotFoundException,IOException{ this.name = in.readUTF(); this.age = in.readInt(); }