Java对象序列化Serializable

序列化概述

简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!
问题的引出:

如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{
A a = new A(); B b = new B();
},这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!
以下序列化机制的解决方案:

1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)
2.当要保存一个对象时,先检查该对象是否被保存了。
3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象
通过以上的步骤序列化机制解决了对象引用的问题!
序列化的实现
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements
Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object
obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
例子:
import java.io.*;

public class Test {
public static void main(String[] args) {
Employee harry = new Employee("Harry Hacker", 50000);
Manager manager1 = new Manager("Tony Tester", 80000);
manager1.setSecretary(harry);

Employee[] staff = new Employee[2];

staff[0] = harry;
staff[1] = manager1;
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("employee.dat"));
out.writeObject(staff);
out.close();

ObjectInputStream in = new ObjectInputStream(new FileInputStream(
"employee.dat"));
Employee[] newStaff = (Employee[]) in.readObject();
in.close();

/**
* 通过harry对象来加薪 将在secretary上反映出来
*/
newStaff[0].raiseSalary(10);

for (int i = 0; i < newStaff.length; i++)
System.out.println(newStaff[i]);
} catch (Exception e) {
e.printStackTrace();
}
}
}

class Employee implements Serializable {
public Employee(String n, double s) {
name = n;
salary = s;
}

/**
* 加薪水
*/
public void raiseSalary(double byPercent) {
double raise = salary * byPercent / 100;
salary += raise;
}

public String toString() {
return getClass().getName() + "[name = " + name + ",salary = " + salary
+ "]";
}

private String name;

private double salary;
}

class Manager extends Employee {
public Manager(String n, double s) {
super(n, s);
secretary = null;
}

/**
* 设置秘书
*/
public void setSecretary(Employee s) {
secretary = s;
}

public String toString() {
return super.toString() + "[secretary = " + secretary + "]";
}

// secretary代表秘书
private Employee secretary;
}

修改默认的序列化机制
在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:
private void readObject(ObjectInputStream in) throws
IOException, ClassNotFoundException;
private void writeObject(ObjectOutputStream out) throws
IOException;
(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)
使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。


下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!
import java.io.*;
import java.awt.geom.*;

public class TransientTest {
public static void main(String[] args) {
LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);
try {
System.out.println(label);// 写入前
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("Label.txt"));
out.writeObject(label);
out.close();

System.out.println(label);// 写入后

ObjectInputStream in = new ObjectInputStream(new FileInputStream(
"Label.txt"));
LabeledPoint label1 = (LabeledPoint) in.readObject();
in.close();
System.out.println(label1);// 读出并加1.0后
} catch (Exception e) {
e.printStackTrace();
}
}

}

class LabeledPoint implements Serializable {
public LabeledPoint(String str, double x, double y) {
label = str;
point = new Point2D.Double(x, y);
}

private void writeObject(ObjectOutputStream out) throws IOException {
/**
* 必须通过调用defaultWriteObject()方法来写入 对象的描述以及那些可以被序列化的字段
*/
out.defaultWriteObject();
out.writeDouble(point.getX());
out.writeDouble(point.getY());
}

private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
/**
* 必须调用defaultReadObject()方法
*/
in.defaultReadObject();
double x = in.readDouble() + 1.0;
double y = in.readDouble() + 1.0;
point = new Point2D.Double(x, y);
}

public String toString() {
return getClass().getName() + "[label = " + label + ", point.getX() = "
+ point.getX() + ", point.getY() = " + point.getY() + "]";
}

private String label;

transient private Point2D.Double point;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值