我们知道对象的持持久化有三种方式:

1: 对象序列化

2: XML

3: 数据库技术

序列化可以帮助使得对象的生命周期不取决与程序是否正在执行,它可以生存于程序的调用之间。 只要将任何对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,并且没有任何重复复制的对象。

序列化技术包括序列化和饭序列化

我们可以通过实现Serializable接口来实现对象的序列化。

class Data implements Serializable{
private int n;
public Data(int i) {
n = i;
}
@Override
public String toString() {
return Integer.toString(n);
}
} /*
* 由于Java序列化似乎找不出什么缺点,所以尽量不要自己动手,让它利用优化的算法自动维护整个对象网
*/
public class Test implements Serializable{
private static Random random = new Random(47);
private Data[] data = {
new Data(random.nextInt(10)),
new Data(random.nextInt(10)),
new Data(random.nextInt(10))
};
private char c;
private Test next;
public Test() {
System.out.println("default constructor ...");
}
public Test(int i, char x){
System.out.println("Test constructor : " + i + " " + x);
c = x;
if (--i > 0) {
next = new Test(i, (char)(x + 1));
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(c + "(");
for (Data d : data) {
sb.append(d);
}
sb.append(")");
if (next != null) {
sb.append(next);
}
return sb.toString();
} public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException{
Test test = new Test(6, 'a');
System.out.println("test : " + test); //序列化到磁盘文件
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Ser.out"));
oos.writeObject("Storage ...");
oos.writeObject(test);
oos.close(); //从磁盘文件中反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Ser.out"));
String s = (String)ois.readObject();
Test t1 = (Test)ois.readObject(); /*
* 通过输出我们可以看到序列化特别聪明的一个地方是它不仅保存了对象的全景图,而且还能追踪对象内部所包含的所有引用,保存那些对象;
* 接着又能对对象内部包含的每个这样的引用进行追踪了,以此类推,通过优化的算法来维护整个对象网
* 序列化的对象在进行反序列化时,内有调用任何构造器。整个对象都是通过InputStrean中去的数据恢复的。
*/
System.out.println("header : " + s);
System.out.println(t1); //序列化到字节数组
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(baos);
oos2.writeObject("Storage2 ...");
oos2.writeObject(t1); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois2 = new ObjectInputStream(bais);
s = (String) ois2.readObject();
t1 = (Test)ois2.readObject(); System.out.println("header : " + s);
System.out.println(t1);
}
}
输出:
Test constructor : 6 a
Test constructor : 5 b
Test constructor : 4 c
Test constructor : 3 d
Test constructor : 2 e
Test constructor : 1 f
test : a(853)b(119)c(802)d(788)e(199)f(881)
header : Storage ...
a(853)b(119)c(802)d(788)e(199)f(881)
header : Storage2 ...
a(853)b(119)c(802)d(788)e(199)f(881)

  

序列化的控制:

1:实现Externalizable接口来对序列化过程进行控制(Externalizable 继承了 Serializable接口)

public class Test implements Externalizable{

	private int i;
private String s;
public Test() {
System.out.println("default constructor ....");
}
public Test(int i,String s){
this.i = i;
this.s = s;
}
@Override
public String toString() {
return s + i;
} /*
* 通过实现Externalizable, 我们要重写下面两个方法,然后在序列化和反序列化的过程中被自动调用,
* 以便完成一些操作
*/
@Override
public void writeExternal(ObjectOutput out) throws IOException {
System.out.println("Test writeExternal");
out.writeObject(s);
out.writeObject(i);
} @Override
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
System.out.println("Test readExternal");
s = (String)in.readObject();
i = (int)in.readObject();
} public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Test test = new Test(47, "a String number");
System.out.println(test);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Ext.out"));
System.out.println("Saving Object...");
oos.writeObject(test);
oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Ext.out"));
System.out.println("Recovering Object...");
/*
* 对于Serializable对象,对象完全以它存储的二进制位为基础,我而不调用构造器
* 而对于Externalizable对象,所有普通默认的构造器都会被调用,然后调用readExternal
*/
Test tmp = (Test)ois.readObject();
System.out.println(tmp); }
}
输出:
a String number47
Saving Object...
Test writeExternal
Recovering Object...
default constructor ....
Test readExternal
a String number47

  

2:transient关键字

transient通常与Serializable一起使用,因为Externalizable直接就可以控制我们要序列化的部分,而Serializable默认的是全部序列化。

使用transient可以逐个字段地关闭序列化,它的意思是“不用麻烦你保存或恢复数据,我自己会处理”

public class Test implements Serializable{

	 private Date date = new Date();
private String username;
private transient String password;
public Test() {}
public Test(String un, String pd) {
username = un;
password = pd;
}
@Override
public String toString() {
return "info : " + "date : " + date + " username : " + username + "password : " + password;
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException{
Test test = new Test("gbx", "gbx");
System.out.println("saving : " + test);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tran.out"));
oos.writeObject(test);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("tran.out"));
Test t1 = (Test)ois.readObject();
//从输出中我们可以看到password为null
System.out.println("recovering : " + t1);
}
} 输出:
saving : info : date : Thu Nov 28 19:25:30 CST 2013 username : gbxpassword : gbx
recovering : info : date : Thu Nov 28 19:25:30 CST 2013 username : gbxpassword : null

  

3: 实现Serializable, 然后自己添加

	private void writeObject(ObjectOutputStream stream) throws IOException{

	}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException{ }

  

public class Test implements Serializable{
private String a;
private transient String b;
public Test(String ai, String bi) {
a = "transient : " + ai;
b = "not transient" + bi;
}
@Override
public String toString() {
return a + "\n" + b;
}
private void writeObject(ObjectOutputStream stream) throws IOException{
System.out.println("invok writeObject");
//调用默认的writeObject
stream.defaultWriteObject();
//如果不进行手动的处理这里的b是不会序列化的
stream.writeObject(b);
}
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException{
System.out.println("invok readObject");
stream.defaultReadObject();
//手动处理
b = (String)stream.readObject();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Test test = new Test("test1", "test2");
System.out.println("saving : \n" + test); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("rw.out"));
oos.writeObject(test);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("rw.out"));
Test t1 = (Test)ois.readObject();
System.out.println("recovering : " + t1);
}
}
输出:
saving :
transient : test1
not transienttest2
invok writeObject
invok readObject
recovering : transient : test1
null

  

对于静态数据 我们必须手动去实现才行。

序列化时,并不保存静态变量,这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量,所以我们要收到实现

public class Test implements Serializable{

	public static int a = 5;
private static int b = 5;
@Override
public String toString() {
return a + " " + b;
}
public static void writeVarB(ObjectOutputStream oos) throws IOException {
oos.writeInt(b);
}
public static void readVarB(ObjectInputStream ois) throws IOException {
b = ois.readInt();
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Test test = new Test(); System.out.println(test); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.out"));
Test.writeVarB(oos);
oos.writeObject(test); test.a = 10; test.b = 10; ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.out"));
Test.readVarB(ois);
Test t1 = (Test)ois.readObject(); /*
* 通过输出可以发现a没有被保存,所以他的值会改变, b被保存了,所以我们读出来的值是我们之前保存的值
*/
System.out.println(t1);
}
} 输出:
5 5
10 5

  

Java I/O 对象序列化的更多相关文章

  1. 【译】Java中的对象序列化

    前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...

  2. Java IO(Properties/对象序列化/打印流/commons-io)

    Java IO(Properties/对象序列化/打印流/commons-io) Properties Properties 类表示了一个持久的属性集.Properties 可保存在流中或从流中加载. ...

  3. 每天进步一点点-Java IO操作-Java Serializable(对象序列化)的理解和总结

    往硬盘文件里写数据 序列化:序列化是将对象转换为容易传输的格式的过程.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.在另一端,反序列化将从该流重 ...

  4. Java基础之对象序列化

    1. 什么是Java对象序列化 Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长.但在现 ...

  5. 【Java基础】对象序列化与读写

    package com.test.io; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...

  6. Java对象序列化文件追加对象的问题,以及Java的读取多个对象的问题解决方法。

    这几天做一个小的聊天项目用到对象序列化的知识,发现对象序列化不能像普通文件一样直接追加对象.每次写入对象都会被覆盖.弄了2个多小时终于解决了.Java默认的对象序列化是每次写入对象都会写入一点头ace ...

  7. java 对象序列化

    java 对象序列化 package org.rui.io.serializable; import java.io.ByteArrayInputStream; import java.io.Byte ...

  8. Java I/O - 对象的输入输出与序列化

    先说概念: 一.相关概念 序列化是Java提供的一种将对象写入到输出流.并在之后将其读回的机制. 序列化:把内存中的java对象转换成与平台无关的二进制字节序列,以便永久保存在磁盘上或通过网络进行传输 ...

  9. Java常用API解析——序列化API

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6797659.html 工作中发现,自己对Java的了解还很片面,没有深入的研究,有很多的J ...

随机推荐

  1. UnicodeDecodeError: ‘ascii’ codec can’t decode...: ordinal not in range(128 问题解决

    UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 108: ordinal not in range(128 原 ...

  2. class id 区别

    [1].id是唯一的,一个元素只能有一个,不能重复class可以重复 <div> <img src="" width="100%"/> ...

  3. Spring AOP:面向切面编程,AspectJ,是基于spring 的xml文件的方法

    导包等不在赘述: 建立一个接口:ArithmeticCalculator,没有实例化的方法: package com.atguigu.spring.aop.impl.panpan; public in ...

  4. nginx安装后出现502 Bad Gateway 错误解决办法

    1. 打开php-fpm.conf 2.将lisen值修改为 listen = 127.0.0.1:9000 并保存 3.重启服务/etc/init.d/php-fpm restart

  5. 用WebDriver实现基于jira过滤器视图的统计自动化

    在Jira上通过过滤器我们可以做出多种视图,以方便统计我们想要收集的结果.比如:我想查看所有分派给我的任务.在Jira上,我保存了一个过滤器,叫做“分派给我的所有任务”.这个过滤器可以过滤出所有分配给 ...

  6. C#实现中国天气网XML接口测试

    点击链接查看中国天气网接口说明,最近想研究一下接口测试,源于最近一次和某公司的技术总监(交大校友)谈话,发现接口测试的需求是比较大的,于是想要研究一下. 好不容易在网上找到了一个关于中国天气网的接口说 ...

  7. C#常用扩展方法

    /// <summary> /// 转换 /// </summary> public static class ConversionHelper { #region 数据格式转 ...

  8. CentOS 安装Redis

    redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcached类似,但很大程度补偿了memcached的不足,它支持存储的value类型相对更多,包括strin ...

  9. 华东交通大学2016年ACM“双基”程序设计竞赛 1001

    Problem Description 输入一个非负的int型整数,是奇数的话输出"ECJTU",是偶数则输出"ACM". Input 多组数据,每组数据输入一 ...

  10. Android OnTouchListener,OnClickListener和OnLongClickListener的关系

    在OnTouchListener事件里有MotionEvent.ACTION_DOWN,MotionEvent.ACTION_UP和MotionEvent.ACTION_MOVE三个事件,我们在这里只 ...