背景

在OOP(面向对象编程)中处处是对象,我们当然希望可以有一种数据格式来存储这种对象的集合,以实现持久化。比如部门类所形成的部门对象集合,员工类所形成的员工对象集合,甚至是这样一个类所形成的对象:公司中有多个部门,每个部门有多个员工,我们希望将这样一个对象以文件的方式实现持久化保存。

对象流的概念

为实现对象的持久化保存,我们需要引入Java语言的对象序列化(object serialization)机制,这种机制可以将任何对象输出到流中:比如

/**
*流对象
*/
Object object = new Object();
//创建对象流并输出到文件object.dat
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("c:\\object.dat"));
//将object对象写到文件中
output.writeObject(object); ObjectInputStream input = new ObjectInputStream(new FileInputStream("c:\\object.dat"));
object = input.readObject();

对象流实例

引入一张组织结构图

定义组织架构图的类
  • 公司:代表了组织架构的外在存在;公司是由部门和职员组成的一个完整实体。
  • 部门:代表了组织架构中的运作单位;部门按类型不同可以分为不同的业务部门。
  • 职员:代表了组织架构中的最小单位;职员按职位不同存在于不同的业务部门。
/**
* 用对象流保存信息--公司类
*
* @author zhuhuix
* @date 2020-05-27
*/
class Company implements Serializable { //公司id
private int id;
//公司名称
private String name;
//公司部门列表
private List<Department> departments; //默认构造函数
Company() {
} //初始化构造函数
Company(int id, String name) {
this.id = id;
this.name = name;
this.departments = new ArrayList<>();
} //增加部门
public void addDepartment(Department department) {
this.departments.add(department);
} //裁撤部门
public void deleteDepartment(Department department) {
this.departments.remove(department);
} //定位部门
Department findDepartmentByName(String departmentName) {
Optional<Department> optional = departments.stream().filter(department ->
department.getName().equals(departmentName)).findFirst();
return optional.get();
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public List<Department> getDepartments() {
return departments;
} public void setDepartments(List<Department> departments) {
this.departments = departments;
}
} /**
* 用对象流保存信息--部门类
*
* @author zhuhuix
* @date 2020-05-27
*/
class Department implements Serializable { //部门id
private int id;
//部门名称
private String name;
//上级部门
private Integer parentId;
//部门职员列表
private List<Employee> employees;
//默认构造函数
Department(){}
//初始化构造函数
Department(int id,String name,Integer parentId){
this.id=id;
this.name=name;
this.parentId=parentId;
this.employees = new ArrayList<>();
}
//增加职员
public void addEmployee(Employee employee){
this.employees.add(employee);
}
//裁撤职员
public void deleteEmployee(Employee employee){
this.employees.remove(employee);
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getParentId() {
return parentId;
} public void setParentId(Integer parentId) {
this.parentId = parentId;
} public List<Employee> getEmployees() {
return employees;
} public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
} /**
* 用对象流保存信息--职员类
*
* @author zhuhuix
* @date 2020-05-27
*/
class Employee implements Serializable { //职员id
private int id;
//职员姓名
private String name;
//职员性别
private String sex;
//职员年龄
private int age;
//职员职位
private String position;
//入职日期
private Date hireDate;
//当前薪水
private BigDecimal salary;
//默认构造函数
Employee(){}
//初始化构造函数
public Employee(int id, String name, String sex, int age, String position, Date hireDate, BigDecimal salary) {
this.id = id;
this.name = name;
this.sex = sex;
this.age = age;
this.position = position;
this.hireDate = hireDate;
this.salary = salary;
} //升职、调岗、调动
public void setPosition(String position){
this.position = position;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getPosition() {
return position;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
} public BigDecimal getSalary() {
return salary;
} public void setSalary(BigDecimal salary) {
this.salary = salary;
}
}
类的完整结构

用对象流保存组织架构的对象信息

有了类及构造函数完成对象的初始化过程,我们就具备了建立整个组织架构的能力,接下来我们完整地建立一个公司的组织架构:

/**
1. 用对象流保存组织架构信息
2. * @author zhuhuix
3. @date 2020-05-27
*/
public class ObjectStreamSave {
//定义一个全局静态变量,作为控制组织架构的id
public static int id = 0; public static void main(String[] args) throws IOException { //设立公司
Company company = new Company(id++, "互联网股份有限公司"); //公司设立总经理室
Department manageDept = new Department(id++, "总经理室", null);
company.addDepartment(manageDept); //在总经理室下设立产品部
Department productDept = new Department(id++, "产品部", manageDept.getId());
company.addDepartment(productDept);
//在产品部下设立产品A、B组
company.addDepartment(new Department(id++, "产品A组", productDept.getId()));
company.addDepartment(new Department(id++, "产品B组", productDept.getId())); //在总经理室下设立研发部
Department developmentDept = new Department(id++, "研发部", manageDept.getId());
company.addDepartment(developmentDept);
//在研发部下设立软件组与硬件组
company.addDepartment(new Department(id++, "软件组", developmentDept.getId()));
company.addDepartment(new Department(id++, "硬件组", developmentDept.getId())); //在总经理室下设立市场部
Department marketDept = new Department(id++, "市场部", manageDept.getId());
company.addDepartment(marketDept);
//在市场部下设立创意组与渠道组
company.addDepartment(new Department(id++, "创意组", marketDept.getId()));
company.addDepartment(new Department(id++, "渠道组", marketDept.getId())); //总经理室人事任命
manageDept.addEmployee(new Employee(id++, "Mike", "男", 35, "总经理",
new Date(), BigDecimal.valueOf(100000)));
manageDept.addEmployee(new Employee(id++, "Tom", "男", 34, "副总经理",
new Date(), BigDecimal.valueOf(60000))); //研发部人事任命
developmentDept.addEmployee(new Employee(id++, "Jack", "男", 30, "研发部主管",
new Date(), BigDecimal.valueOf(40000)));
company.findDepartmentByName("软件组")
.addEmployee(new Employee(id++, "Kate", "女", 26, "组员",
new Date(), BigDecimal.valueOf(20000)));
company.findDepartmentByName("硬件组")
.addEmployee(new Employee(id++, "Will", "男", 24, "组员",
new Date(), BigDecimal.valueOf(20000))); //产品部人事任命
productDept.addEmployee(new Employee(id++, "Jerry", "男", 28, "产品部主管",
new Date(), BigDecimal.valueOf(40000)));
company.findDepartmentByName("产品A组")
.addEmployee(new Employee(id++, "Merry", "女", 28, "组员",
new Date(), BigDecimal.valueOf(20000)));
company.findDepartmentByName("产品B组")
.addEmployee(new Employee(id++, "Leo", "男", 27, "组员",
new Date(), BigDecimal.valueOf(20000))); //市场部人事任命
marketDept.addEmployee(new Employee(id++, "Rose", "女", 29, "市场部主管",
new Date(), BigDecimal.valueOf(40000)));
company.findDepartmentByName("创意组")
.addEmployee(new Employee(id++, "Amy", "", 25, "组员",
new Date(), BigDecimal.valueOf(20000)));
company.findDepartmentByName("渠道组")
.addEmployee(new Employee(id++, "Tony", "男", 23, "组员",
new Date(), BigDecimal.valueOf(20000))); //遍历公司组织结构
int deptCount = 0;
int empCount = 0;
Iterator<Department> deptIterator = company.getDepartments().iterator();
while (deptIterator.hasNext()) {
deptCount++;
Department department = deptIterator.next();
System.out.println("部门:" + department.getName());
if (department.getEmployees() != null) {
Iterator<Employee> empIterator = department.getEmployees().iterator();
while (empIterator.hasNext()) {
empCount++;
Employee employee = empIterator.next();
System.out.print(" 人员:" + employee.getName() + " 职位:" + employee.getPosition() + ",");
}
System.out.println();
}
}
System.out.println("总共部门数:" + deptCount);
System.out.println("总共职员数:" + empCount); //通过对象流将公司组织架构保存到文件中
ObjectOutputStream companyStream = new ObjectOutputStream(new FileOutputStream("c:\\company.dat"));
companyStream.writeObject(company);
companyStream.writeObject(company.getDepartments());
for (int i = 0; i < company.getDepartments().size(); i++) {
List<Employee> employees = company.getDepartments().get(i).getEmployees();
companyStream.writeObject(employees);
} }
}
核心代码
  1. 通过对象流的方式建立一个company.dat文件
  2. 将公司对象写入文件
  3. 将公司对象中的部门列表集合写入文件
  4. 遍历部门列表,将每个部门下的职员列表集合写入文件



生成的文件如下:



二进制信息:

用对象流读取文件并输出
/**
* 用对象流读取信息
*
* @author zhuhuix
* @date 2020-05-27
*/
public class ObjectStreamRead {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream companyStream = new ObjectInputStream(new FileInputStream("c:\\company.dat"));
if (companyStream!=null){
Company company=(Company) companyStream.readObject(); //遍历公司组织结构
int deptCount = 0;
int empCount = 0;
Iterator<Department> deptIterator = company.getDepartments().iterator();
while (deptIterator.hasNext()) {
deptCount++;
Department department = deptIterator.next();
System.out.println("部门:" + department.getName());
if (department.getEmployees() != null) {
Iterator<Employee> empIterator = department.getEmployees().iterator();
while (empIterator.hasNext()) {
empCount++;
Employee employee = empIterator.next();
System.out.print(" 人员:" + employee.getName() + " 职位:" + employee.getPosition() + ",");
}
System.out.println();
}
}
System.out.println("总共部门数:" + deptCount);
System.out.println("总共职员数:" + empCount); } }
}
核心代码
  1. 通过对象流的方式获取company.dat文件
  2. 读取对象信息



输出如下:

总结

在本文中,我们使用序列化将对象集合保存到磁盘文件中,并按照它们被存储的样子获取它们,我们学习到了如下信息:

  • ObjectOutputStream(OutputStream out) 创建一个ObjectOutputStream使得你可以将对象写出到指定的OutputStream。
  • void writeObject(Object obj) 写出指定的对象到ObjectOutputStream,这个方法将存储指定对象的类、类的签名以及这个类及其超类中所有非静态和非瞬时的域的值。
  • ObjectInputStream(InputStream in) 创建一个ObjectInputStream用于从指定的InputStream中读回对象信息。
  • Object readObject()从ObjectInputStream中读入一个对象。特别是,这个方法会读回对象的类、类的签名以及这个类及其超类中所有非静态和非瞬时的域的值。它执行的反序列化允许恢复多个对象引用。

用非常硬核的JAVA序列化手段实现对象流的持久化保存的更多相关文章

  1. Java自学-I/O 对象流

    Java 对象流 ObjectInputStream,ObjectOutputStream 对象流指的是可以直接把一个对象以流的形式传输给其他的介质,比如硬盘 一个对象以流的形式进行传输,叫做序列化. ...

  2. 硬核剖析Java锁底层AQS源码,深入理解底层架构设计

    我们常见的并发锁ReentrantLock.CountDownLatch.Semaphore.CyclicBarrier都是基于AQS实现的,所以说不懂AQS实现原理的,就不能说了解Java锁. 上篇 ...

  3. JAVA序列化和反序列化 对象<=>IO流 对象<=>字节数组

    http://developer.51cto.com/art/201202/317181.htm http://blog.csdn.net/earbao/article/details/4691440 ...

  4. java学习之IO对象流

    //注意对象类要打标记实现Serializable接口 package com.gh; import java.io.FileInputStream; import java.io.FileNotFo ...

  5. java获取远程网络图片文件流、压缩保存到本地

    1.获取远程网路的图片 /** * 根据地址获得数据的字节流 * * @param strUrl * 网络连接地址 * @return */ public static byte[] getImage ...

  6. Netty 系列之 Netty 高性能之道 高性能的三个主题 Netty使得开发者能够轻松地接受大量打开的套接字 Java 序列化

    Netty系列之Netty高性能之道 https://www.infoq.cn/article/netty-high-performance 李林锋 2014 年 5 月 29 日 话题:性能调优语言 ...

  7. Java序列化与反序列化

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  8. [转] Java序列化与反序列化

    原文地址:http://blog.csdn.net/wangloveall/article/details/7992448 Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java ...

  9. 编解码-java序列化

    大多数Java程序员接触到的第一种序列化或者编解码技术就是Java的默认序列化,只需要序列化的POJO对象实现java.io.Serializable接口,根据实际情况生成序列ID,这个类就能够通过j ...

随机推荐

  1. 数据库SQL---实体-联系模型(E-R模型)

    1.E-R模型的基本概念与表示 1)实体与实体集 (1)实体:可以是有形的.实在的事物(如每个员工),可以是抽象的.概念上存在的事物(如一个部门). (2)实体的特征:独立存在.可区别于其他实体. ( ...

  2. 学习HTML

    前端三剑客:HTML.CSS.JavaScript.现在就开始学习HTML啦. 学习资源:http://www.freecodecamp.cn/ 学习笔记: h1,head1,一级标题 <h1& ...

  3. 创造DotNet Core轻量级框架【一】

    前言 net core 已经出了很久了,网上的各种框架也很多了,但是没看到一个很小很轻的框架,基本都是那种啥功能都有,但是我需要的功能只占他们框架的百分之几,很少很少,所以自己创造一个框架. 因为之前 ...

  4. C语言程序报告五

    C程序设计实验报告 姓 名:赖瑾 实验地点:家 实验时间: 2020年4月21日 实验项目:6.3.1练习1 编写由三角形三边求面积的函数 6.3.1练习2 编写求N阶乘的函数 6.3.1练习3 求两 ...

  5. D - Pearls HDU - 1300 斜率dp+二分

    D - Pearls HDU - 1300 这个题目也是一个比较裸的斜率dp,依照之前可以推一下这个公式,这个很好推 这个注意题目已经按照价格升序排列序,所以还是前缀和还是单调的. sum[i] 表示 ...

  6. 线段树 B数据结构 牛客练习赛28

    链接:https://ac.nowcoder.com/acm/contest/200/B来源:牛客网 题目描述 qn姐姐最好了~     qn姐姐给你了一个长度为n的序列还有m次操作让你玩,     ...

  7. 第3章:关系数据库标准语言 SQL

    目录 第3章:关系数据库标准语言 SQL 3.1.SQL概述 3.1.1.历史 3.3.2.SQL语言的功能 3.3.3.SQL的特点 3.3.4.基本概念 3.2.学生-课程数据库 3.3.数据定义 ...

  8. Java流式思想和方法引用

    目录 Java流式思想和方法引用 1. Stream流 1.1 概述 传统集合的多步遍历代码 Stream的更优写法 1.2 流式思想的概述 1.3 获取流 1.4 常用方法 ①逐一处理:forEac ...

  9. springboot使用druid连接池连接Oracle数据库的基本配置

    #阿里连接池配置 #spring.datasource.druid.driver-class-name=oracle.jdbc.driver.OracleDriver #可配可不配,阿里的数据库连接池 ...

  10. 【mybatis】IF判断的坑

    http://cheng-xinwei.iteye.com/blog/2008200 最近在项目使用mybatis中碰到个问题 <if test="type=='y'"> ...