序列化是Java中非常重要且常用的一个功能。它在实现网络通信、分布式存储等方面都有广泛的应用。而序列化版本号serialVersionUID则是保证序列化的兼容性和稳定性的重要手段,它用于判断序列化对象的版本是否一致,如果不一致则不能反序列化。
在Java中,每个class都有一个serialVersionUID属性,它是一个长整型数字。如果不显式指定,Java会自动生成一个serialVersionUID。当对象被序列化时,Java会将序列化对象的对象流中写入serialVersionUID,并且在反序列化时校验该数字。
serialVersionUID的作用就是当序列化一个对象时,Java会判断这个对象的serialVersionUID和本地JVM中对应的serialVersionUID是否一致。如果一致,则可以反序列化这个对象;如果不一致,则会抛出InvalidClassException异常,反序列化失败。
示例一:同一版本的序列化和反序列化
import java.io.*;
public class SerializationTest {
private static final String FILE_PATH = "user.ser";
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User("张三", 20);
System.out.println("序列化前: " + user);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH));
oos.writeObject(user);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH));
User newUser = (User)ois.readObject();
ois.close();
System.out.println("序列化后: " + newUser);
}
private static class User implements Serializable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
}
执行结果如下:
序列化前: User{name='张三', age=20}
序列化后: User{name='张三', age=20}
示例二:不同版本的序列化和反序列化
import java.io.*;
public class SerializationTest {
private static final String FILE_PATH = "user.ser";
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User("张三", 20);
System.out.println("序列化前: " + user);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH));
oos.writeObject(user);
oos.close();
// 修改User对象的属性age的类型为long
File file = new File(FILE_PATH);
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
byte[] bytes = new byte[(int)randomAccessFile.length()];
randomAccessFile.readFully(bytes);
bytes[43] = 0x4C; // 修改0x10为0x4C
randomAccessFile.seek(0);
randomAccessFile.write(bytes);
randomAccessFile.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH));
User newUser = (User)ois.readObject();
ois.close();
System.out.println("序列化后: " + newUser);
}
private static class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private long age;
public User(String name, long age) {
this.name = name;
this.age = age;
}
// 省略 toString 方法
}
}
执行结果如下:
序列化前: User{name='张三', age=20}
Exception in thread "main" java.io.InvalidClassException: SerializationTest$User; local class incompatible: stream classdesc serialVersionUID = 7528517758001900623, local class serialVersionUID = 1
可以看到,当User对象被成功序列化后,我们故意修改了其属性age的类型,并重新读取了文件进行反序列化,我们得到了一个InvalidClassException异常的提示,反序列化失败。
在以上两个示例中,我们可以看到serialVersionUID属性的作用。当我们使用序列化功能时,一定要注意并理解这个字段的含义,以防止在使用中产生意外的错误。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:序列化版本号serialVersionUID的作用_动力节点Java学院整理 - Python技术站