首先,创建一个自定义类
class Goods implements Serializable{
//Serializable接口是用来标志该类可序列化,其没有需要重写的方法
final static long serialVersionUID= 37689563422L;
//serialVersionUID的作用在下文解释
private String id;
private String name;
private double price;
public Goods() {
}
public Goods(String id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "goods{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", price=" + price +
'}';
}
}
一般来说类里面的属性应该加上限制条件,例如名称长短,年龄的范围等,我这里没加。
然后写序列化类的测试类
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String path="文件地址";
Goods goods=new Goods("001","coke",78);
//创建对象
OutputStream outputStream=new FileOutputStream(path);
//搭建从内存到硬盘的管道
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(goods);
//将类序列化后写入文件中
objectOutputStream.close();
outputStream.close();
//打开后要关闭流,遵守先开后关的原则
/*InputStream inputStream=new FileInputStream(path);
ObjectInputStream objectInputStream=new ObjectInputStream(inputStream);
Object obj=objectInputStream.readObject();
Goods goods=(Goods) obj;
System.out.println(goods);
objectInputStream.close();
inputStream.close();*/
}
}
序列化后的结果(是一串看不懂的字符串,也没必须看懂)如下
sr GoodsPS ??T D priceL idt Ljava/lang/String;L nameq ~ xp@S€ t 001t coke
反序列化类的测试类
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String path="C:\\Users\\阳\\Desktop\\2.txt";
/*Goods goods=new Goods("001","coke",78);
OutputStream outputStream=new FileOutputStream(path);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(goods);
objectOutputStream.close();
outputStream.close();*/
InputStream inputStream=new FileInputStream(path);
//搭建从硬盘到内存的管道
ObjectInputStream objectInputStream=new ObjectInputStream(inputStream);
Object obj=objectInputStream.readObject();
//用Object类接收反序列化的返回值,readObject()用于读取文件内容并反序列化
Goods goods=(Goods) obj;
//将Object类强制转化为Goods类
System.out.println(goods);
objectInputStream.close();
inputStream.close();
}
}
打印结果如下
goods{id='001', name='coke', price=78.0}
讲一下serialVersionUID的作用,例如我在一次序列化后,在反序列化之前在自定义类中再加一个属性,此时会报错如下
Exception in thread "main" java.io.InvalidClassException: Goods; local class incompatible: stream classdesc serialVersionUID = 37689563422, local class serialVersionUID = 5787978497880964692
at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:728)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2062)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1909)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1744)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472)
at pta.main(pta.java:14)
其中第一句最重要
Exception in thread "main" java.io.InvalidClassException: Goods; local class incompatible: stream classdesc serialVersionUID = 37689563422, local class serialVersionUID = 5787978497880964692
它告诉我们:stream classdesc serialVersionUID = 37689563422, local class serialVersionUID = 5787978497880964692,也就是反序列化回来的serialVersionUID与本地serialVersionUID不匹配,如果类中没有serialVersionUID系统会给个默认值,值会随时间和类的改变而改变,所以造成了不匹配,所以serialVersionUID的作用是保证反序列化后能成功匹配
final static long serialVersionUID= 37689563422L;
//final是代表不可更改的修饰符,serialVersionUID应为一个常值
transient private String name;
//transient代表不可序列化,可以避免序列化不需要序列化的值
以上是上课的内容,后来我试了一下,还可以序列化集合,自定类不变,测试类如下
public class pta {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String path="C:\\Users\\阳\\Desktop\\2.txt";
/*ArrayList<Goods> arrayList=new ArrayList<>();
Goods goods=new Goods("001","coke",78);
Goods goods1=new Goods("002","test",90);
arrayList.add(goods);
arrayList.add(goods1);
OutputStream outputStream=new FileOutputStream(path);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(arrayList);
objectOutputStream.close();
outputStream.close();*/
InputStream inputStream=new FileInputStream(path);
ObjectInputStream objectInputStream=new ObjectInputStream(inputStream);
ArrayList<Object> arrayList= (ArrayList<Object>) objectInputStream.readObject();
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
objectInputStream.close();
inputStream.close();
}
}
序列化过程是被注释的内容,反序列化后的结果打印如下
goods{id='001', name='null', price=78.0}
goods{id='002', name='null', price=90.0}
由于我在类中的name属性前加了transient关键词所以默认为null,还有更多的东西需要自己去发掘