• 对象的序列化


  • 什么是Java对象的序列化?

对象序列化的目标是将对象保存到磁盘上,或允许在网络中直接传输对象。对象序列化机制允许把内存中的Java对象转换成与平台无关的二进制流,从而保存或者传输。其他的程序一旦获得这种二进制流,还可以把这种二进制流恢复成原来的Java对象

序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础。要养成良好的习惯,在写一个javabean的时候都要去实现Serializable接口。



如果需要让某个对象支持序列化机制,则必须让的类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:Serializable;Externalizable。在实际开发中一般都是直接实现Serializable就好了,后面一种不怎么使用,至少我从来没有用过。

  • 关于这2者的区别:

1:Serializable  系统自动存储必要信息,在使用的时候只需要实现接口,无需其他的代码支持,性能略差。

2:Externalizable 程序员决定存储哪些信息,在使用的必须实现这个接口里面的2个空方法(一个读,一个写),性能略好。

  •   关于Java对象的序列化,要有一个值得理解的地方就是Java序列化机制的序列化算法:

1,所有保存到磁盘中的对象都有一个序列化编号

  2,当程序试图去系列化一个对象时,首先会去检查这个对象是否已经被序列化了

  3,要是对象已经被序列化过了,那好,程序就直接输出一个序列化编号,而不是再次重新序列化该对象

  4,要是这个对象没有被序列化过,那好,程序会将这个对象转换成字节序列然后输出



那么问题来了: 

1,要是我连续2次调用了ObjectOutputStream的writeobject方法去序列化一个对象,然后在中间过程中我修改了这个对象的属性,那么这个修改操作会生效么?    不会生效,因为第2次序列化并没有实际发生,只是输出了一个序列号号而已。

    2,反序列化读取的是什么?是Java对象的数据还是Java类呢?  明显的:Java的反序列化读取的是Java对象的数据,所以我们在采用反序列化恢复Java数据时,一定要提供Java对象所属类的class文件,否则将引发ClassNotFoundException。

    3,反序列化机制在恢复Java对象时,无须调用构造器来初始化对象。如果一个类的构造器是private的,但是反序列化依然可以创建Java对象,如何解决这个问题呢?关于这点,其实我理解也不深刻。有一个解决方案就是:重写readResolve()方法。

    4,反序列化Java对象必须提供这个对象所属类的class文件,现在的问题是随着项目的升级,系统的class文件也会跟着改变,Java如何保证2个class文件的兼容性呢?   这个时候版本号派上用场了(private static final long serialVersionUID = 1L)。版本号用来标示Java类的序列号版本,不管一个类有没有升级和改变,只要他的版本号不变,序列化机制就会把他们当成同一个序列化版本。



    在这里严肃的批评下自己,每天在写Javabean,每次都觉得生成那个serialVersionUID太麻烦,就把myeclipse设置了下不提示这个版本号了,这个习惯不好,一定要改过来,另外的,在使用有引用的Java对象时,注意要把所有的类都去实现Serializable接口,这样子就会保证序列化和反序列化都正常。如果某个类的字段不是基本数据类型或 String  类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的
Field 的类也不能序列化。



import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable; /**
*
* @version 1L
* @author LinkinPark
* @since 2014-12-31
* @motto 梦似烟花心似水,同学少年不言情
* @desc ^ 注意这里序列化对象,也使用了IO流,所以最后不要忘记去关闭流
*/
public class Linkin
{ public static void main(String[] args) throws Exception
{
//创建一个ObjectOutputStream输出流,这是一个处理流,包装了一个普通的低级流
ObjectOutputStream oos = null;
//创建一个ObjectInputStream输入流,同样也是一个处理流,包装了一个普通的低级流
ObjectInputStream ois = null;
try
{
//第一次输出对象
oos = new ObjectOutputStream(new FileOutputStream("src/LinkinPark..."));
Person person = new Person();
person.setName("LinkinPark...");
person.setAge(25);
oos.writeObject(person);
//第2次输出对象,这里只是输出了一个序列化号
oos = new ObjectOutputStream(new FileOutputStream("src/LinkinPark1..."));
oos.writeObject(person); ois = new ObjectInputStream(new FileInputStream("src/LinkinPark..."));
Person person1 = (Person) ois.readObject();
System.out.println("这里是反序列化之后的对象:" + person1.getName() + ";" + person1.getAge());
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (oos != null)
{
oos.close();
}
if (ois != null)
{
ois.close();
}
}
}
} //定义一个类,只要实现Serializable就表示这个对象是可以序列化的,其实实现这个接口IDE会提示要初始化一个版本号的,只不过我自己设置过了不再提示了
class Person implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private Integer age; public Person()
{
//下面这行代码不会执行的
System.out.println("反序列化机制在恢复Java对象时,无须调用构造器来初始化对象");
}
public String getName()
{
return name;
} public void setName(String name)
{
this.name = name;
} public Integer getAge()
{
return age;
} public void setAge(Integer age)
{
this.age = age;
} }

  • 自定义序列化

在一些特殊的情况下,我们不希望某个类中的一些信息被序列化,这个时候就要自定义序列化了。

有2种做法:

1,这种比较简单的,就是在我们不希望序列化的属性前面加上transient就好了。注意了:transient只能用于修饰属性,不可修饰Java的其他成员。使用这种方式很方便的,但是有一个缺陷的:被transient修饰的属性完全隔离在序列化机制之外,这样会导致反序列化恢复Java对象时无法获取该属性值。

2,通过自定义序列化机制可以让程序控制如何序列化各个成分。在需要特殊处理的类中提供如下3个方法,就可以实现了,使用情景不是很多,了解下就好了。

private void wirteObject(ObjectOutputStream out):写对象

private void readObject(ObjectInputStream in):读对象

private void readObjectNoData():当序列流不完整的时候,用来正确初始化反序列化的对象

输入和输出--java序列化机制的更多相关文章

  1. Java序列化机制

    java的序列化机制支持将对象序列化为本地文件或者通过网络传输至别处, 而反序列化则可以读取流中的数据, 并将其转换为java对象. 被序列化的类需要实现Serializable接口, 使用Objec ...

  2. Java序列化机制和原理及自己的理解

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

  3. Java序列化机制和原理

    Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程:反序列化deserialization是一种将这些字节重建成一个对象的过程.Java序列化API提供一 ...

  4. Java序列化机制剖析

    本文转载自longdick的博文<Java序列化算法透析>,原文地址:http://longdick.iteye.com Java序列化算法透析 Serialization(序列化)是一种 ...

  5. hadoop序列化机制与java序列化机制对比

    1.采用的方法: java序列化机制采用的ObjectOutputStream 对象上调用writeObject() 方法: Hadoop 序列化机制调用对象的write() 方法,带一个DataOu ...

  6. 输入和输出--java的NIO

    Java的NIO 实际开发中NIO使用到的并不多,我并不是说NIO使用情景不多,是说我自己接触的并不是很多,前面我在博客园和CSDN上转载了2篇别人写的文章,这里来大致总结下Java的NIO,大概了解 ...

  7. Java I/O系统学习系列五:Java序列化机制

    在Java的世界里,创建好对象之后,只要需要,对象是可以长驻内存,但是在程序终止时,所有对象还是会被销毁.这其实很合理,但是即使合理也不一定能满足所有场景,仍然存在着一些情况,需要能够在程序不运行的情 ...

  8. Java序列化机制原理

      Java序列化就是将一个对象转化为一个二进制表示的字节数组,通过保存或则转移这些二进制数组达到持久化的目的.要实现序列化,需要实现java.io.Serializable接口.反序列化是和序列化相 ...

  9. 细看Java序列化机制

    概况 在程序中为了能直接以 Java 对象的形式进行保存,然后再重新得到该 Java 对象,这就需要序列化能力.序列化其实可以看成是一种机制,按照一定的格式将 Java 对象的某状态转成介质可接受的形 ...

随机推荐

  1. 深入设计电子计算器(一)——CPU指令集设计

    版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/8254096.html 作者:窗户 Q ...

  2. 分布式文件系统FastDFS如何做到高可用

    FastDFS是用C语言编写的一款开源的轻量级分布式文件系统.它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以文件为载体的 ...

  3. 使用jemeter手工编写注册、登陆脚本 运用 fiddler (一)

    我们要使用jemeter来手工写一个脚本 我们要使用到两个工具 一个 就是  jmeter  一个就是 fiddler 为什么要使用fiddler   ? 因为能够帮我们正确精准的找到我们需要的数据 ...

  4. C# 构造函数总结

    构造函数 构造函数分为:实例构造函数,静态构造函数,私有构造函数. 实例构造函数 1.构造函数的名字与类名相同. 2.使用 new 表达式创建类的对象或者结构(例如int)时,会调用其构造函数.并且通 ...

  5. React Native学习(三)—— 使用导航器Navigation跳转页面

    本文基于React Native 0.52 参考文档https://reactnavigation.org/docs/navigators/navigation-prop 一.基础 1.三种类型 Ta ...

  6. Elastic FileBeat 快速入门

    背景 用过ELK(Elasticsearch, Logstash, Kibana)的人应该都面临过同样的问题,Logstash虽然功能强大:支持许多的input/output plugin.强大的fi ...

  7. A + B Problem II(大数加法)

    http://acm.hdu.edu.cn/showproblem.php?pid=1002 A + B Problem II Time Limit: 2000/1000 MS (Java/Other ...

  8. [国嵌攻略][077][Linux时间编程]

    时间类型 Coordinated Universal Time(UTC):世界标准时间,也就是格林威治时间(Greenwich Mean Time, GMT). Calendar Time:日历时间, ...

  9. 【深度学习系列】CNN模型的可视化

    前面几篇文章讲到了卷积神经网络CNN,但是对于它在每一层提取到的特征以及训练的过程可能还是不太明白,所以这节主要通过模型的可视化来神经网络在每一层中是如何训练的.我们知道,神经网络本身包含了一系列特征 ...

  10. Hadoop 发行版本 Hortonworks 安装详解(二) 安装Ambari

    一.通过yum安装ambari-server 由于上一步我们搭建了本地源,实际上yum是通过本地源安装的ambari-server,虽然也可以直接通过官方源在线安装,不过体积巨大比较费时. 这里我选择 ...