08.序列化和Json解析
1.序列化的概念
序列化:(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程,具体到过程是将数据结构或者对象转化为二进制或字符串的过程.
反序列化: 将序列化之后的二进制转换为数据结构或者是对象的过程.
持久化:将对象或者数据结构序列化后的二进制以文件形式存储起来.
序列化方案:
-
Serializable/Externalizable
-
Parcelable
-
json,xml,probuf...等等,属于广义的序列化
2.Serializable/Externalizable
2.1 Serializable 的序列化
在使用序列化时候,保证对象都有无参的构造函数,因为序列化会反射产生一个新的对象.
主要是使用ObjectOutputStream的方法,来进行序列化操作.
-
public final void writeObject(Object obj) throws IOException用来将对象写入指定的输出流 将文件写入到指定的输出流. 使用transient关键字 忽略一些关键字的序列化. 也可以实现两个方法实现精细化管理序列化字段,系统在序列化时候会反射调用这两个方法.private void writeObject(ObjectOutputStream out) throws IOException和private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException -
使用SerialVersionUID 来进行版本管理,反序列化时候检测到版本不一致会报错.
2.2 Externalizable 序列化
Externalizable 接口要求类需要显示的实现对象的序列化过程,即实现接口要求得两个序列化方法.
public void writeExternal(ObjectOutput out) throws IOException序列化过程方法,要求序列化过程要和反序列化的顺序是一致的.public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException反序列化过程方法,要求过程要和序列化的顺序是一致的.
举例如下: 几个序列化的类
public class User implements Serializable {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Dog implements Externalizable {
private String name;
private int age;
public Dog() {
}
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;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeInt(age);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
age = in.readInt();
}
}
public class Person implements Serializable {
transient private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();//本方法是实现默认序列化的方法
out.writeInt(age);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject(); //本方法是实现默认反序列化的方法
age = in.readInt();
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
序列化操作:
public class SerializableUtils {
public static void serializableObj(@NotNull Object obj, @NotNull String path) throws Exception {
final File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(path));) {
outputStream.writeObject(obj);
}
}
public static <T> T unSerializableObj(String path) throws Exception {
try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(path));) {
final Object o = objectInputStream.readObject();
objectInputStream.close();
return (T) o;
}
}
public static void exInSerialTest(Object o, String path) {
File file = new File(path);
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
FileOutputStream outputStream = new FileOutputStream(file);) {
byte[] buf = null;
objectOutputStream.writeObject(o);
buf = byteArrayOutputStream.toByteArray();
outputStream.write(buf);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object exInSerialTest(String path) {
File file = new File(path);
byte[] buf = new byte[(int) file.length()];
try (FileInputStream inputStream = new FileInputStream(file);) {
final int read = inputStream.read(buf);
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
ObjectInputStream objectOutputStream = new ObjectInputStream(byteArrayInputStream);) {
final Object o = objectOutputStream.readObject();
return o;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public static byte[] objectToBytes(Object object) {
if (Objects.isNull(object)) {
return null;
}
if (!(object instanceof Serializable)) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
return outputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Object arrayToObject(byte[] array) {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(array);
try {
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
final Object o = objectInputStream.readObject();
return o;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
执行测试方法:
public class Main {
public static void main(String[] args) {
personOut();
}
public void ObjToFile() {
User user = new User("zhangsan", 14);
try {
SerializableUtils.serializableObj(user, "zhangsan.out");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void personIn() {
Person person = new Person();
person.setAge(10);
try {
SerializableUtils.serializableObj(person, "person.out");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void personOut() {
try {
final Object o = SerializableUtils.unSerializableObj("person.out");
System.out.println((Person) o);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void fileToObj() {
Object o = null;
try {
o = SerializableUtils.unSerializableObj("zhangsan.out");
} catch (Exception e) {
e.printStackTrace();
}
if (o instanceof User) {
System.out.println(o);
}
}
public static void writeDogExternal() {
Dog dog = new Dog();
dog.setAge(12);
dog.setName("ddd");
SerializableUtils.exInSerialTest(dog, "dog.out");
}
public static void readDogExternal() {
final Object o = SerializableUtils.exInSerialTest("dog.out");
System.out.println(o);
}
}
序列化是直接从二进制文件中生成的对象,不会调用对象的构造方法。序列化类似于一个深拷贝,对象的地址完全不同,对象的内容属性才是相同的。序列化是为了进程之间进行交换数据为目的,持久化是为了把文件保存到本地,持久化可以基于序列化。