java序列化:为什么序列化,为什么实现Serializable,serialVersionUID拿来干嘛?

1.序列化的概念:

序列化 :(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程【百度百科】
咋一看,专业术语发懵!!

2.序列化的理解:

问1:为什么序列化,要将对象的状态信息转换为可以“存储或者传输”的形式?
答1:计算机保存的数据是二级制数据(0和1),也就是数字
问2:那么。如何将“对象的状态信息”的信息状态“转化二级制数据”?
答2:如果要将“文本,图片,视频等信息储存在电脑中,就需要序列化(也就是将文本,图片,视频等信息转化为二进制数据,保存在电脑中)”

3.举个例子:

序列化的过程,其实在java IO流中就已经有体会了!!

例子1:

之前接触的序列化,将文本信息存到电脑的:D:\test.txt

/**
* 将文本写入磁盘
*/
public class Test {
public static void main(String[] args) throws Exception {
// 对于java代码,是将信息输出到磁盘中对应----> output流
FileOutputStream fileOutputStream = new FileOutputStream("D:\\test.txt");
// 写入的内容
String text = "序列化";
// 将文本转化为字节byte,
byte[] bytes = text.getBytes();
// 将信息写入磁盘
fileOutputStream.write(bytes);
// 关闭流
fileOutputStream.close();
}
}

// 在盘中,节能看到文件:test.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
重点:String类型本身有getBytes()方法,将文本转换为字节码
以上的过程,将文本信息转化为字节byte(转化为byte字节序列),然后流对象帮我们写磁盘中
那么反序列化呢?也就相当于我们读取:test.txt中的信息

/**
* 读取文本
* ASCII码:一个英文字母(不分大小写)占一个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数。换算为十进制 ,最小值-128,最大值127。如一个ASCII码就是一个字节。
* UTF-8编码:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。中文标点占三个字节,英文标点占一个字节
* Unicode编码:一个英文等于两个字节,一个中文(含繁体)等于两个字节。中文标点占两个字节,英文标点占两个字节
*/
public class Test {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("D:\\test.txt");
// 序列化是三个字,utf-8下,一个字符是三个字节,三个字是九个字节
byte[] bytes = new byte[9];
// 将D:\test.txt的信息转化为byte字节
int length = fileInputStream.read(bytes);
// 将字节转化为文本信息
String s = new String(bytes, 0, length);
System.out.println(s); // 输出:序列化
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
例子2:

在玩游戏的时候,你的信息(玩家昵称,等级信息,玩家年龄等)往往存在电脑中,等你再玩该游戏的时候,再将等级信息等读取出来,那么一个实体类,怎么存到电脑中?
重点:自定义实体类,没有getByte()方法,怎么进行传输?

/**
* 将对象信息存储到磁盘中
*/
public class Test {
public static void main(String[] args) throws Exception {
// 创建User实例
User user = new User("小白",3,99);
// 创建文件流对象
FileOutputStream fileOutputStream= new FileOutputStream("D:\\user.txt");
// 之前是通过对象.getBytes()方法,然后写到流中,但User是我们自己创建的类,没有该方法,用java提供的ObjectOutputStream对象流
// 将文件流对象给对象流
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
// 对象流将对象信息写入D:\\user.txt中
outputStream.writeObject(user);
// 关闭流
outputStream.close();
fileOutputStream.close();
}
}


/**
* user类
*/
public class User {
private String name; // 用户名称
private int age; // 用户年龄
private int level; // 游戏等级
public User(String name, int age, int level) {
this.name = name;
this.age = age;
this.level = level;
}
public User() {
super();
}
// getter和setter省略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
运行上面的程序:报错!!

Exception in thread "main" java.io.NotSerializableException: serialization.User
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at serialization.Test.main(Test.java:17)
1
2
3
4
结果告诉我们,User类没序列化!!!怎么办???Java中给我提供一个接口Serializable,源码如下

public interface Serializable {
}
1
2
问:可是接口什么都没有啊,实现了有什么用?
答:java让你实现该接口,就为了告诉程序,这个能序列化,你不实现,门都没有!!相当于给实现的类一个通行证
实现一下:

/**
* user类
*/
public class User implements Serializable {
private String name; // 用户名称
private int age; // 用户年龄
private int level; // 游戏等级
public User(String name, int age, int level) {
this.name = name;
this.age = age;
this.level = level;
}
public User() {
super();
}
// getter和setter省略
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
运行程序,再去看:D:\user.txt文件的信息,这是什么鬼?

看不懂,不要紧,我们只是要将信息储存在电脑中,目的已经达到了!!!

反序列化一下:

/**
* 读取D:\\user.txt信息
*/
public class Test {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream = new FileInputStream("D:\\user.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
User user = (User)objectInputStream.readObject();
System.out.println(user);
objectInputStream.close();
fileInputStream.close();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
输出:serialization.User@58372a00
1
得到的是一个对象的地址:那我们来toString(),看看他的庐山真面目:

/**
* user类
*/
public class User implements Serializable {
private String name;
private int age;
private int level;

public User(String name, int age, int level) {
this.name = name;
this.age = age;
this.level = level;
}
public User() {
super();
}
// getter和setter省略

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", level=" + level +
'}';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
再次运行:

Exception in thread "main" java.io.InvalidClassException: serialization.User; local class incompatible: stream classdesc serialVersionUID = 4255073330490321173, local class serialVersionUID = -6139716091850480259
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at serialization.Test.main(Test.java:15)

1
2
3
4
5
6
7
8
9
serialVersionUID = 4255073330490321173;这个好像有点熟悉,是什么呢?
报错信息,序列化的id不一致!什么意思?(User类的序列化id和磁盘文件D:\user.txt中的序列化id不一致),Serializable源码注释也有说明
看看该博客的解释:https://blog.csdn.net/jediael_lu/article/details/26813153
我们给实体类,加上序列化id

/**
* user类
*/
public class User implements Serializable {
private static final long serialVersionUID = 4125096758372084309L;
private String name;
private int age;
private int level;
public User(String name, int age, int level) {
this.name = name;
this.age = age;
this.level = level;
}
public User() {
super();
}
// getter和setter省略

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", level=" + level +
'}';
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
要重新序列化生成D:\user.txt文件,再次反序列化:

输出结果:User{name='小白', age=3, level=99}
1
好啦!!!
问:为什么序列化?
问:为什么实现Serializable?
问:还要加上private static final long serialVersionUID = 4125096758372084309L;
希望能对读者有帮助!

其他:
IDEA实现序列化接口Serializable自动生成serialVersionUID
(idea2019位置:Setting->Editor->Inspections->Java->Serialization issues->Serializable class without ’serialVersionUID’)
---------------------

猜你喜欢

转载自www.cnblogs.com/liyanyan665/p/11198605.html