序列化和反序列化
package oo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @author 45~
* @version 1.0
* 使用ObjectOutputStream,完成数据的序列化
*/
public class OutputStream_ {
public static void main(String[] args) throws Exception {
//序列化后保存的文件不是纯文本的,而是按照他的数据格式来保存
//所以此处写.txt格式也没用
String filePath = "e:\\data.datuuu";
//创建序列化对象,由于是对文件进行操作,所以传入节点流FileOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到e:\data.dat
//保存的数据实质上是个对象,要实现Serializable接口
oos.writeInt(100);//能保存100,因为int在底层能够自动装箱成Integer,Integer实现了Serializable接口
oos.writeBoolean(true);//以下均能自动装箱成包装类
oos.writeChar('a');
oos.writeDouble(9.5);
//此处其实是将String放进去,String也是实现了Serializable接口的,所以可以序列化。
oos.writeUTF("不教一日闲过也");//注意放字符串的方法是UTF,而非String
//保存一个实现了序列化接口的对象
oos.writeObject(new Dog("旺财",10));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
package II;
import oo.Dog;//输出的Dog即公有的,此处注意不在同一个包里要访问要做成共有的
import java.io.*;
/**
* @author 45~
* @version 1.0
* 反序列化
*/
public class OObjectInputStream {
public static void main(String[] args) throws IOException, ClassNotFoundException {//第二个是抛出类型转换异常
//确定从哪个文件去读取进行反序列化
String filePath = "E:\\data.datuuu";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取顺序,即反序列化的顺序需要和(保存数据)序列化的顺序一致,否则一定会报异常。
//因为序列化(保存)是按顺序来保存数据类型和值到文件里边的,而反序列化是将数据和类型又读到程序里边了。
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
//dog的编译类型是Object,运行类型是Dog
Object dog = ois.readObject();//读对象,底层会把Object转型成Dog
System.out.println("运行类型=" + dog.getClass());
System.out.println("dog信息="+dog);
//如果需要调用Dog的方法,需要向下转型
//需要我们将Dog类定义,拷贝到可以引用的位置,不管是不是在同一个包,只要能引用就行
//比如是public类,虽然不在同一个包也可以引用,若引用不到是转换不了的
/*Dog dog2 =(Dog)dog;向下转型会提示没有此名称
"'oo.Dog' is not public in 'oo'. Cannot be accessed from outside package"
说明要用此Dog方法原先的类定义需要拿过来
*/
Dog dog2 =(Dog)dog;
System.out.println(dog2.getName());//旺财
//System.out.println(ois.readObject());//因为在读时底层会把Object进行转型成一只狗
//关闭外层流,底层会自动关闭传入的字节流FileInputStream(即真正干活的节点流)
ois.close();
/*(1)运行出现“Exception in thread "main" java.io.InvalidClassException”无效类型异常,
是因为Dog类出现在OO包里。即在进行转换时,II包里也应该有类的定义,这是必须的。
(2)在进行反序列化时一定要把类拿到,若无程序是跑不起来的。
(3)重要细节:如果类里边有方法,此处简单用Getter和Setter方法,
如果希望调用Dog类里的方法,那么需要向下转型
Object dog = ois.readObject();//底层会把Object转型成Dog,
虽然此处的运行类型是Dog,编译调方法dog.getName()通不过哦,Object类里没有此方法。
*/
}
}
/*
//将Dog类拿过来
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
//若序列化时不定义toString方法,显示"dog信息=oo.Dog@58372a00"
//当定义了toString方法就需要重新执行一遍
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
*/
/*运行报错“Exception in thread "main" java.io.InvalidClassException: oo.Dog;
local class incompatible:
stream classdesc serialVersionUID = 553920722521361545,
local class serialVersionUID = 8155589668217606734”
Dog拷贝过来后需要重新生成一下,因为不重新生成认为版本不是统一的,
因为有序列化问题,所以先运行OutoutStream_.java序列化,再运行此反序列化。
报错二:“Exception in thread "main" java.lang.ClassCastException:
oo.Dog cannot be cast to II.Dog
at II.OObjectInputStream.main(OObjectInputStream.java:32)”
在序列化时已经将Dog的包写出来了,所以包要么保持一致,要么用序列化的方式来处理。
解决办法:将Dog类公有化拿到外面
*/