Java SerialVersionUID作用详解

网友投稿 468 2022-10-05


Java SerialVersionUID作用详解

问题1:Serializable是什么

首先,说说Serializable是实现java将内存中的类存储至硬盘中而使用的

一个类使用了Serializalbe接口,在序列化到文件时,会有一个SerialVersionUID。

这个东东是用于对类进行版本控制的。

首先看Person类清单:

=====

import java.io.Serializable;

public class Person implements Serializable {

//如果没有指定serialVersionUID,系统会自动生成一个

private static final long serialVersionUID = 1L;

private String name;

//添加这么一个成员变量

private String address; //序列化后如果之前版本没有,就为null

public String getName() {

// int a = 100;

// for(int i=0;i

// name+=i;

// }

return name;

}

public void setName(String name) {

this .name = name;

}

}

===== 然后是测试类清单 =====

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

/**

* if Object implements Serializable without Uid,

* system will automatically give this object a uid by algorithm

* @author v11

* @date 2014年9月18日

* @version 1.0

*/

public class WhySerialversionUID {

public static void objectToFile(Object obj,String fileName) throws Exception{

ObjectOutputStream oo = new ObjectOutputStream( new FileOutputStream(

fileName));

oo.writeObject(obj);

oo.close();

}

public static Object getObjectFromFile(String fileName) throws Exception {

ObjectInputStream oi = new ObjectInputStream( new FileInputStream(

fileName));

Person crab_back = (Person) oi.readObject();

http://oi.close();

return crab_back;

}

public static void main(String[] args) throws Exception {

String fileName = "crab_file" ; //文件名

// 这里是把对象序列化到文件

Person crab = new Person();

crab.setName( "Mr.Crab" );

//储存到文件中

//objectToFile(crab,fileName);

// 这里是把对象序列化到文件,我们先注释掉,一会儿用

Person crabBack = (Person) getObjectFromFile(fileName);

//Dog crabBack = (Dog) getObjectFromFile(fileName);

System.out.println( "Hi, My name is " + crabBack.getName());

}

}

=http://====

1.对于Person类中,将变量 address和SerialVersionUID注释掉,存储到文件,并读出。显示正常

2.将变量address还原,读取原来存储的文件,显示异常。抛出错误 InvalidClassException。

原因如下:

因为我们没有指定SerialVersionUID,因此系统自动生成了一个serialVersionUID(这个是根据类名,变量名,方法名)生成的

但是改动后的Person中变量名有变动,于是这个UID就不一样了,对于版本控制就无法读取。

所以,大家在很多代码里看到把UID设置为1L,就是Person代码中那样。

将Person代码UID设置为1L,再重复上述步骤,不报错。那么就意味着如果你选择将UID设置为1L,就是选择了兼容类的版本不一致。

PS:为什么说自动生成的 serialVersionUID是根据 类名,变量名,方法名,因为当你在原有的类的方法内进行添加内容,并不是对最后系统生成的UID造成影响,即不会抛出错误

问题2:所有类都设置为1L,是否有不良影响,不同类会不会冲突

public class Dog implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this .name = name;

}

}

新定义Dog类如上,将测试类代码中Dog的赋值注释去掉

//Dog crabBack = (Dog) getObjectFromFile(fileName);

运行结果抛出错误:

Exception in thread "main" java.lang.ClassCastException: serializable.Person cannot be cast to serializable.Dog

说明serializable在不同类一间并不矛盾。

// name+=i;

// }

return name;

}

public void setName(String name) {

this .name = name;

}

}

===== 然后是测试类清单 =====

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

/**

* if Object implements Serializable without Uid,

* system will automatically give this object a uid by algorithm

* @author v11

* @date 2014年9月18日

* @version 1.0

*/

public class WhySerialversionUID {

public static void objectToFile(Object obj,String fileName) throws Exception{

ObjectOutputStream oo = new ObjectOutputStream( new FileOutputStream(

fileName));

oo.writeObject(obj);

oo.close();

}

public static Object getObjectFromFile(String fileName) throws Exception {

ObjectInputStream oi = new ObjectInputStream( new FileInputStream(

fileName));

Person crab_back = (Person) oi.readObject();

http://oi.close();

return crab_back;

}

public static void main(String[] args) throws Exception {

String fileName = "crab_file" ; //文件名

// 这里是把对象序列化到文件

Person crab = new Person();

crab.setName( "Mr.Crab" );

//储存到文件中

//objectToFile(crab,fileName);

// 这里是把对象序列化到文件,我们先注释掉,一会儿用

Person crabBack = (Person) getObjectFromFile(fileName);

//Dog crabBack = (Dog) getObjectFromFile(fileName);

System.out.println( "Hi, My name is " + crabBack.getName());

}

}

=http://====

1.对于Person类中,将变量 address和SerialVersionUID注释掉,存储到文件,并读出。显示正常

2.将变量address还原,读取原来存储的文件,显示异常。抛出错误 InvalidClassException。

原因如下:

因为我们没有指定SerialVersionUID,因此系统自动生成了一个serialVersionUID(这个是根据类名,变量名,方法名)生成的

但是改动后的Person中变量名有变动,于是这个UID就不一样了,对于版本控制就无法读取。

所以,大家在很多代码里看到把UID设置为1L,就是Person代码中那样。

将Person代码UID设置为1L,再重复上述步骤,不报错。那么就意味着如果你选择将UID设置为1L,就是选择了兼容类的版本不一致。

PS:为什么说自动生成的 serialVersionUID是根据 类名,变量名,方法名,因为当你在原有的类的方法内进行添加内容,并不是对最后系统生成的UID造成影响,即不会抛出错误

问题2:所有类都设置为1L,是否有不良影响,不同类会不会冲突

public class Dog implements Serializable{

private static final long serialVersionUID = 1L;

private String name;

public String getName() {

return name;

}

public void setName(String name) {

this .name = name;

}

}

新定义Dog类如上,将测试类代码中Dog的赋值注释去掉

//Dog crabBack = (Dog) getObjectFromFile(fileName);

运行结果抛出错误:

Exception in thread "main" java.lang.ClassCastException: serializable.Person cannot be cast to serializable.Dog

说明serializable在不同类一间并不矛盾。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【内网学习笔记】29、白银票据(白银票据利用)
下一篇:什么是SQL注入、XSS以及CSRF?【网络安全知识培训】(sql注入攻击和xss攻击的主要区别)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~