1.谈到了序列化,那么我们必须要知道Java里面的序列化接口Serializable
,相信大家打开这个类想查看源码时没结果发现这个接口竟然是空的。 想必这时候大家肯定是一脸懵逼, 一个空接口能实现什么功能呢,其实啊,这个Serializable
接口的作用只有标识作用,即只是个标识接口。我们可以举个例子:
比如在课堂上有位学生遇到一个问题,于是举手向老师请教,这时老师帮他解答,那么这位学生的举手其实就是一个标识,自己解决不了问题请教老师帮忙解决。在Java中的这个Serializable接口其实是给jvm看的,通知jvm,我不对这个类做序列化了,你(jvm)帮我序列化就好了。
因此大家应该也明白了,Serializable
接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可,当然了,通过这个接口的注释也可以看出,它强烈建议我们自己定义一个serialversionUID,因为默认生成的serialversionUID对class极其敏感,在反序列化的时候很容易抛出InvalidClassException异常。
2.既然已经了解了这个序列化接口Serializable
,那么就可以写序列化和反序列化了,所谓序列化就是指将对象转换为字节序列的过程
,说白了,就是将序列化的对象存储成文件
,直接看代码吧:
(1).首先就是转化的对象User类,代码如下:
typescript
package com.example.main;
import java.io.Serializable;
//序列化的对象必须实现Serializable接口。
public class User implements Serializable{
private String name;
private String passWord;
public User(String name, String passWord) {
this.name = name;
this.passWord = passWord;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
//此处之所以写toString()方法就是为了方便反序列化后能够在终端看到我们能看懂的字符串,而不是类名和哈希码。
//因为每个Java类都默认继承了Object类,而且此处就算不写重写注解也无妨,但是为了便于阅读,还是建议写上好。
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", passWord='" + passWord + ''' +
'}';
}
}
(2).以下代码就是主方法执行序列化操作。
java
package com.example.main;
import java.io.*;
public class Main {
public static void main(String[] args) {
//里面的./就是进入根目录。
File file = new File("./name.txt");
try {
//如果文件路径不存在,那么就会创建一个。
if (file.createNewFile()){
System.out.println("创建成功");
} else {
System.out.println("文件已经创建");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
//以下就是序列化过程,好好思考一下。
User user = new User("jinxuan",21);
try {
//注意由于这里是要将对象写入文件,故应该使用objectOutputStream类。
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream(file));
stream.writeObject(user);
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
但是我们通过查看name.txt文件就会发现里面都是乱码,这是因为我们在写入二进制数据而不是文件。
3.既然序列化完了,肯定就该反序列化了,反序列化就是序列化的反过程,将字节序列转换为JAVA对象
,直接看代码如下:
代码如下:
java
package com.example.main;
import java.io.*;
public class Main {
public static void main(String[] args) {
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("./name.txt"));
try {
Object o = objectInputStream.readObject();
User user = (User) o;
System.out.println(user);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
关于我们上面说到的SerialVersionUID ,这个可以的话必须要自己定义一个,而且尽量用Private 修饰,因为这个也没必要让外部类修改,之所以加上这个ID的目的就是为了在反序列化的时候操作系统会进行检测这个ID和序列化的时候的ID是否相同再进行反序列化,而JVM之所以会默认生成这样一个SerialVersionUID就是为了使其可以进行持久化,即有了标记才可以使得JVM允许其IO系统将其转换为字节数据。