## 一、将类转化为可序列化的类 在类的定义中实现接口`Serializable`即可将类转变为可序列化的类。 ```javascript import java.io.Serializable; public class Dept implements Serializable { private int deptno; private String dname; private String loc; private transient String password;// 使用transient标记不需要序列化的属性 public Dept() { } public Dept(int deptno, String dname, String loc, String password) { this.deptno = deptno; this.dname = dname; this.loc = loc; this.password = password; } public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + ", password='" + password + '\'' + '}'; } } ``` ## 二、对象的序列化 “低级流”:`FileOutputStream` “高级流”:`ObjectOutputStream` ``` Dept dept = new Dept(12,"张三","辽宁","test123"); File path = new File("./class/src/test/java/TestFile/fileStudy"); File objectFile = new File(path, "test.obj"); FileOutputStream out = null; ObjectOutputStream oout = null; try { if (!objectFile.exists()) { if (objectFile.createNewFile()) System.out.println("test.obj文件创建成功"); } out = new FileOutputStream(objectFile); oout = new ObjectOutputStream(out); oout.writeObject(dept); } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { if (oout != null) { oout.close(); } if (out != null) { out.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } ``` ## 三、对象的反序列化 “低级流”:`FileInputStream` “高级流”:`ObjectInputStream` ``` File path = new File("./class/src/test/java/TestFile/fileStudy"); File objectFile = new File(path, "test.obj"); FileInputStream in = null; ObjectInputStream oin = null; try { in = new FileInputStream(objectFile); oin = new ObjectInputStream(in); Dept dept = (Dept) oin.readObject(); System.out.println(dept.toString()); } catch (IOException | ClassNotFoundException e) { System.out.println(e.getMessage()); } finally { try { if (oin !=null){ oin.close(); } if (in!=null){ in.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } ``` 因为`password`属性为`transient`所以未被序列化  ## 四、关键特性与注意事项 #### 1、字段控制 * `transient` 关键字:标记不参与序列化的字段 * 静态(static)字段:自动不参与序列化(属于类,不属于对象) #### 2、版本控制 * `serialVersionUID`:唯一标识类的序列化版本 ```javascript private static final long serialVersionUID = 1L; ``` * 作用:防止序列化不兼容 * 最佳实践:显式声明serialVersionUID #### 3、自定义序列化 * 通过以下方法控制序列化过程: ```javascript private void writeObject(ObjectOutputStream out) throws IOException private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException ``` #### 4、安全性问题 * 不可信任的反序列化可能导致安全问题 * 解决方案: * 验证输入数据来源 * 使用白名单机制 * 避免直接反序列化不可信数据 #### 5、继承关系 * 父类序列化:子类自动可序列化 * 父类未序列化:需有无参构造方法(反序列化时调用) ## 五、总结 | 特性 | 序列化 | 反序列化 | | ------------ | ------------------ | ----------------- | | **目的** | 对象 → 字节流 | 字节流 → 对象 | | **核心接口** | Serializable | Serializable | | **关键类** | ObjectOutputStream | ObjectInputStream | | **版本控制** | serialVersionUID | serialVersionUID | | **字段控制** | transient关键字 | transient关键字 | | **安全性** | 较低风险 | 较高风险 | Loading... ## 一、将类转化为可序列化的类 在类的定义中实现接口`Serializable`即可将类转变为可序列化的类。 ```javascript import java.io.Serializable; public class Dept implements Serializable { private int deptno; private String dname; private String loc; private transient String password;// 使用transient标记不需要序列化的属性 public Dept() { } public Dept(int deptno, String dname, String loc, String password) { this.deptno = deptno; this.dname = dname; this.loc = loc; this.password = password; } public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + ", password='" + password + '\'' + '}'; } } ``` ## 二、对象的序列化 “低级流”:`FileOutputStream` “高级流”:`ObjectOutputStream` ``` Dept dept = new Dept(12,"张三","辽宁","test123"); File path = new File("./class/src/test/java/TestFile/fileStudy"); File objectFile = new File(path, "test.obj"); FileOutputStream out = null; ObjectOutputStream oout = null; try { if (!objectFile.exists()) { if (objectFile.createNewFile()) System.out.println("test.obj文件创建成功"); } out = new FileOutputStream(objectFile); oout = new ObjectOutputStream(out); oout.writeObject(dept); } catch (IOException e) { System.out.println(e.getMessage()); } finally { try { if (oout != null) { oout.close(); } if (out != null) { out.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } ``` ## 三、对象的反序列化 “低级流”:`FileInputStream` “高级流”:`ObjectInputStream` ``` File path = new File("./class/src/test/java/TestFile/fileStudy"); File objectFile = new File(path, "test.obj"); FileInputStream in = null; ObjectInputStream oin = null; try { in = new FileInputStream(objectFile); oin = new ObjectInputStream(in); Dept dept = (Dept) oin.readObject(); System.out.println(dept.toString()); } catch (IOException | ClassNotFoundException e) { System.out.println(e.getMessage()); } finally { try { if (oin !=null){ oin.close(); } if (in!=null){ in.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } ``` 因为`password`属性为`transient`所以未被序列化  ## 四、关键特性与注意事项 #### 1、字段控制 * `transient` 关键字:标记不参与序列化的字段 * 静态(static)字段:自动不参与序列化(属于类,不属于对象) #### 2、版本控制 * `serialVersionUID`:唯一标识类的序列化版本 ```javascript private static final long serialVersionUID = 1L; ``` * 作用:防止序列化不兼容 * 最佳实践:显式声明serialVersionUID #### 3、自定义序列化 * 通过以下方法控制序列化过程: ```javascript private void writeObject(ObjectOutputStream out) throws IOException private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException ``` #### 4、安全性问题 * 不可信任的反序列化可能导致安全问题 * 解决方案: * 验证输入数据来源 * 使用白名单机制 * 避免直接反序列化不可信数据 #### 5、继承关系 * 父类序列化:子类自动可序列化 * 父类未序列化:需有无参构造方法(反序列化时调用) ## 五、总结 | 特性 | 序列化 | 反序列化 | | ------------ | ------------------ | ----------------- | | **目的** | 对象 → 字节流 | 字节流 → 对象 | | **核心接口** | Serializable | Serializable | | **关键类** | ObjectOutputStream | ObjectInputStream | | **版本控制** | serialVersionUID | serialVersionUID | | **字段控制** | transient关键字 | transient关键字 | | **安全性** | 较低风险 | 较高风险 | 最后修改:2025 年 10 月 13 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 👆请简单粗暴地爱我。