1.序列化 Serializable
MySerialize.java
package my.java.serialize;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
/*
* 对象序列化 允许把内存中的java对象转换成平台无关的二进制流,从而允许将这种二进制流持久的保存在磁盘,或者通过网络传输
* 反序列化 将上述的二进制流恢复成原来的java对象
*
* ObjectOutputStream 将序列化对象写入文件
* ObjectInputStream 反序列化
*
* 两种方式 实现Serializable 接口
* 实现Externalizable 接口
*/
public class MySerialize {
public static void main(String[] args) throws Exception {
//myserialize1();
//序列化机制 同一个对象 只在最开始的时候 序列化一次
//1.所有保存到磁盘中的对象都有一个序列化编号
//2.当程序视图序列化一个对象时,首先检查该对象是否被序列化过,只有该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列并输出
//3.如果某个对象已经被序列化,程序将只是直接输出一个序列化编号,而不是再次重新序列化该对象
myserialize2();
}
private static void myserialize1() throws Exception {
//使用该方式 将对象以二进制流输出到文件 即 字节流 以文本方式打开文件是乱码
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
User user1 = new User("张三", new Date(), 20);
User user2 = new User("张四", new Date(), 21);
User user3 = new User("张五", new Date(), 22);
//该方式输入文件的是字节流
outputStream.writeObject(user1);
outputStream.writeObject(user2);
outputStream.writeObject(user3);
outputStream.close();
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
User user11 = (User) inputStream.readObject();
User user22 = (User) inputStream.readObject();
User user33 = (User) inputStream.readObject();
inputStream.close();
System.out.println(user11.toString());
System.out.println(user22.toString());
System.out.println(user33.toString());
}
private static void myserialize2() throws Exception {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object2.txt"));
User user = new User("张三", new Date(), 20);
System.out.println(user.toString());
outputStream.writeObject(user);
user.setName("张四");
user.setBirthday(new Date());
user.setAge(21);
System.out.println(user.toString());
outputStream.writeObject(user);
outputStream.close();
System.out.println("-----------分界线--------------");
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object2.txt"));
User user11 = (User) inputStream.readObject();
User user22 = (User) inputStream.readObject();
inputStream.close();
System.out.println(user11.toString());
System.out.println(user22.toString());
/* 输出结果
User [name=张三, birthday=Fri Jun 02 11:16:29 CST 2017, age=20]
User [name=张四, birthday=Fri Jun 02 11:16:29 CST 2017, age=20]
-----------分界线--------------
User [name=张三, birthday=Fri Jun 02 11:16:29 CST 2017, age=20]
User [name=张三, birthday=Fri Jun 02 11:16:29 CST 2017, age=20]*/
}
}
User.java
package my.java.serialize;
import java.io.Externalizable;
import java.io.Serializable;
import java.util.Date;
/*
* 对象序列化 允许把内存中的java对象转换成平台无关的二进制流,从而允许将这种二进制流持久的保存在磁盘,或者通过网络传输
* 反序列化 将上述的二进制流恢复成原来的java对象
*
* 两种方式 实现Serializable 接口
* 实现Externalizable 接口
*/
public class User implements Serializable {
/**
* 版本值 为了在反序列化时确保序列化版本的兼容性
* 标识该java类的序列化版本 如果一个类升级后,只要serialVersionUID值不变,序列化机制会把他们当成同一个序列化版本
*
* 如果不显式指定 serialVersionUID,该值由JVM根据类的相关信息计算,而修改后的类的计算结果与修改之前的类的计算结果往往不同,
* 从而造成对象的反序列化因为类版本不兼容而失败
*/
private static final long serialVersionUID = 1L;
private String name;
private Date birthday;
private int age;
public User(String name, Date birthday, int age) {
super();
this.name = name;
this.birthday = birthday;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", birthday=" + birthday + ", age=" + age + "]";
}
}
2. 序列化 Serializable
MySerialize2.java
package my.java.serialize;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
/*
* 对象序列化 允许把内存中的java对象转换成平台无关的二进制流,从而允许将这种二进制流持久的保存在磁盘,或者通过网络传输
* 反序列化 将上述的二进制流恢复成原来的java对象
*
* ObjectOutputStream 将序列化对象写入文件
* ObjectInputStream 反序列化
*
* 两种方式 实现Serializable 接口
* 实现Externalizable 接口
*
* 自定义序列化
*
* transient 关键字 只能修饰实例变量 指定java序列化时无须理会该实例变量
* private transient Date birthday;
*/
public class MySerialize2 {
public static void main(String[] args) throws Exception {
// 测试 transient
//myserialize();
// 在User2中添加 writeObject readObject 方法进行测试
//myserialize2();
// 在User2类中添加 writeReplace 方法 进行测试
//myserialize3();
}
private static void myserialize() throws Exception {
//使用该方式 将对象以二进制流输出到文件 即 字节流 以文本方式打开文件是乱码
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
User2 user1 = new User2("张三", new Date(), 20);
User2 user2 = new User2("张四", new Date(), 21);
User2 user3 = new User2("张五", new Date(), 22);
//该方式输入文件的是字节流
outputStream.writeObject(user1);
outputStream.writeObject(user2);
outputStream.writeObject(user3);
outputStream.close();
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
User2 user11 = (User2) inputStream.readObject();
User2 user22 = (User2) inputStream.readObject();
User2 user33 = (User2) inputStream.readObject();
inputStream.close();
System.out.println(user11.toString());
System.out.println(user22.toString());
System.out.println(user33.toString());
/* 输出结果 输出时 birthday为null
User [name=张三, birthday=null, age=20]
User [name=张四, birthday=null, age=21]
User [name=张五, birthday=null, age=22]*/
}
private static void myserialize2() throws Exception {
//使用该方式 将对象以二进制流输出到文件 即 字节流 以文本方式打开文件是乱码
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object2.txt"));
User2 user1 = new User2("张三abc", new Date(), 20);
User2 user2 = new User2("张四abc", new Date(), 21);
User2 user3 = new User2("张五abc", new Date(), 22);
//该方式输入文件的是字节流
outputStream.writeObject(user1);
outputStream.writeObject(user2);
outputStream.writeObject(user3);
outputStream.close();
//写入文件的类型是 my.java.serialize.User2
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object2.txt"));
User2 user11 = (User2) inputStream.readObject();
User2 user22 = (User2) inputStream.readObject();
User2 user33 = (User2) inputStream.readObject();
inputStream.close();
System.out.println(user11.toString());
System.out.println(user22.toString());
System.out.println(user33.toString());
/* 输出结果
User [name=cba三张, birthday=Fri Jun 02 13:14:01 CST 2017, age=20]
User [name=cba四张, birthday=Fri Jun 02 13:14:01 CST 2017, age=21]
User [name=cba五张, birthday=Fri Jun 02 13:14:01 CST 2017, age=22]*/
}
@SuppressWarnings("unchecked")
private static void myserialize3() throws Exception {
//使用该方式 将对象以二进制流输出到文件 即 字节流 以文本方式打开文件是乱码
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object3.txt"));
User2 user1 = new User2("张三abc", new Date(), 20);
User2 user2 = new User2("张四abc", new Date(), 21);
User2 user3 = new User2("张五abc", new Date(), 22);
//该方式输入文件的是字节流
outputStream.writeObject(user1);
outputStream.writeObject(user2);
outputStream.writeObject(user3);
outputStream.close();
//如果User2类中的 writeReplace return this; 参考myserialize2 输出
//写入文件的类型是 java.util.ArrayList
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object3.txt"));
ArrayList<Object> list = (ArrayList<Object>) inputStream.readObject();
inputStream.close();
System.out.println(list);
/* 输出结果
[1, 2, 3] */
}
}
User2.java
package my.java.serialize;
import java.io.Externalizable;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
/*
* 对象序列化 允许把内存中的java对象转换成平台无关的二进制流,从而允许将这种二进制流持久的保存在磁盘,或者通过网络传输
* 反序列化 将上述的二进制流恢复成原来的java对象
*
* 两种方式 实现Serializable 接口
* 实现Externalizable 接口
* 自定义序列化
*
* transient 关键字 只能修饰实例变量 指定java序列化时无须理会该实例变量
*/
public class User2 implements Serializable {
/**
* 版本值 为了在反序列化时确保序列化版本的兼容性
* 标识该java类的序列化版本 如果一个类升级后,只要serialVersionUID值不变,序列化机制会把他们当成同一个序列化版本
*
* 如果不显式指定 serialVersionUID,该值由JVM根据类的相关信息计算,而修改后的类的计算结果与修改之前的类的计算结果往往不同,
* 从而造成对象的反序列化因为类版本不兼容而失败
*/
private static final long serialVersionUID = 1L;
private String name;
private transient Date birthday;
private int age;
private void writeObject(ObjectOutputStream out) throws Exception {
//执行默认的序列化机制
out.defaultWriteObject();
//将name实例变量反转后写入二进制流
out.writeObject(new StringBuffer(name).reverse());
//将birthday写入二进制流
out.writeObject(birthday);
}
//重写writeReplace方法 程序在序列化对象之前,先调用该方法
//如果该方法返回另一个java对象 则系统转化为序列化另一个对象
private Object writeReplace() {
//执行writeObject序列化 正常序列化
//return this;
ArrayList<Object> list = new ArrayList<Object>();
list.add(1);
list.add(2);
list.add(3);
return list;
}
private void readObject(ObjectInputStream in) throws Exception {
//执行默认的序列化机制
in.defaultReadObject();
//不更改name顺序
this.name = in.readObject().toString();
//读入birthday
this.birthday = (Date) in.readObject();
}
public User2() {
System.out.println("----不-------带参数的构造器-----------");
}
public User2(String name, Date birthday, int age) {
super();
System.out.println("-----------带参数的构造器-----------");
this.name = name;
this.birthday = birthday;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", birthday=" + birthday + ", age=" + age + "]";
}
}
3. 序列化 Externalizable
MyExternalizable.java
package my.java.serialize;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
public class MyExternalizable {
public static void main(String[] args) throws Exception {
//使用该方式 将对象以二进制流输出到文件 即 字节流 以文本方式打开文件是乱码
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
User3 user1 = new User3("张三", new Date(), 20);
User3 user2 = new User3("张四", new Date(), 21);
User3 user3 = new User3("张五", new Date(), 22);
//该方式输入文件的是字节流
outputStream.writeObject(user1);
outputStream.writeObject(user2);
outputStream.writeObject(user3);
outputStream.close();
// 解析字节流
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
User3 user11 = (User3) inputStream.readObject();
User3 user22 = (User3) inputStream.readObject();
User3 user33 = (User3) inputStream.readObject();
inputStream.close();
System.out.println(user11.toString());
System.out.println(user22.toString());
System.out.println(user33.toString());
/* 输出结果 输出时 birthday为null
------不------带参数构造器------
------不------带参数构造器------
------不------带参数构造器------
User3 [name=三张, birthday=null, age=20]
User3 [name=四张, birthday=null, age=21]
User3 [name=五张, birthday=null, age=22]*/
}
}
User3.java
package my.java.serialize;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Date;
public class User3 implements Externalizable {
/**
* 版本值 为了在反序列化时确保序列化版本的兼容性
* 标识该java类的序列化版本 如果一个类升级后,只要serialVersionUID值不变,序列化机制会把他们当成同一个序列化版本
*
* 如果不显式指定 serialVersionUID,该值由JVM根据类的相关信息计算,而修改后的类的计算结果与修改之前的类的计算结果往往不同,
* 从而造成对象的反序列化因为类版本不兼容而失败
*/
private static final long serialVersionUID = 1L;
private String name;
private Date birthday;
private int age;
//没有序列化 birthday
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(new StringBuffer(name).reverse());
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.name = in.readObject().toString();
this.age = in.readInt();
}
//当使用Externalizable 机制反序列化对象时, 程序会先使用public的无参数构造器创建实例
//然后才执行readExternal 方法进行序列化
//因此实现Externalizable 必须提供无参数构造器
public User3() {
System.out.println("------不------带参数构造器------");
}
public User3(String name, Date birthday, int age) {
super();
System.out.println("------带参数构造器------");
this.name = name;
this.birthday = birthday;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User3 [name=" + name + ", birthday=" + birthday + ", age=" + age + "]";
}
}