对序列化和反序列化的理解

楼主的问题很有意思,不过你对序列化和反序列的应用场景搞错了,我们说的序列化和反序列化是对JAVA而言(其他面向对象语言可能也有)的,序列化的实体是个对象,结果也是个对象,并非是格式化文本,你在记事本里看到的购物信息保存记录,其实不是对象序列化的结果,而是对象输出的格式化文本,真正的序列化对象是看不懂的。

在实际使用对象序列化时,一种应用场景是将对象序列化到持久化存储(本地硬盘),我们此时不想做文件解析,也不想有人读懂这个持久化文件,当我们需要时,可以直接采用反序列化将保存的文件生成为对象;另一种应用场景是在网络传输过程中,此时对象会在不同主机上传播,序列化会将对象转成码流由对端进行解析,这个解析过程不需要人参与。

普通字符串是经过解析后的对象,有对象到字符串要加入解析逻辑,人才能看懂。
序列化的结果是个只有JAVA虚拟机认识的文件,人不参与,只是用于保存对象或传输。

解决你的问题了么?
追问
序列化和购物信息记录里的字符串有关系吗?比如我不序列化,这些字就不能保存到硬盘了吗?

还一个就是序列化以后保存的对象在哪里啊,是购物信息记录里面的文字吗?都一起保存到硬盘上面了?还是放哪里,比如我打开购物信息记录里面只有:某某于某天购物等等,这里面哪有对象啊,跟看文本文件没区别啊,那咱们老说保存对象对象的 我不明白这个对象到底在哪里,和字符串有什么关系没
追答
序列化和字符串没有关系。

字符串是对象里的某些数据的输出结果,你看到的文本文件只包含了对象的一部分信息,你看到可能只是个值而已。

比如一个对象
object monkey
{
    String monkeyName = "悟空";

    long monkeyAge = 1000;

}

你输出的字符串可能只是这个:

悟空;
10000;

但对象很多信息丢掉了,比如对象名称,字段属性之类的。

序列化时把对象完整的输入到某个地方,比如文件,这个文件人类是看不懂的,但在反序列化时,文件就会被完成的读取为一个对象,和上面的对象一模一样,这样我们就可以在代码中对对象进行直接操作了。

are we clear?
追问
good!,原来如此,但是另一个问题又来了,对象保存在哪里?是跟我的文本文件一起保存到硬盘里吗?比如我的文本里字符串是5个字符串文字,按一个字符是2字节,大小是10字节,那如果按你的说法,把字段 名称也保持了,那文件的内容会增多,那有可能不是10字节了,因为你还保存了字段 属性名什么的,那岂不是多占我硬盘空间了?
追答
保存在哪里是你控制的,你想输出到文件系统也可以,其他地方也行。

你说的大小我不知道跟什么比较,一般情况下肯定会比只保存字符串要大,毕竟有其他的信息需要存储。

会多占你些空间,但比起你手动反序列化这些成本还是值得的。
追问
我的意思是说,你序列化以后保存的对象内容,是不是也在最终产生的文本文件里?
比如生成了一个购物信息记录.txt的文件,这里面假如有购物信息这4个文字,那对象能在文本里看到吗?还是只能看到字符串?保存的对象其实也在这个文件里,但是不会输出显示,而且最重要的是文件的大小在电脑里还是显示4个字符的大小,但是对象它也是存在的也占硬盘空间,只不过系统只显示字符串的大小而已?
追答
文本文件是用来保存文本的,是你在代码里控制生成txt。

对象序列化生成的序列化文件,跟txt文件没有关系,你序列化之后存成什么样的文件格式,存储到什么位置,是自己控制的。

你不应该认为txt存储对象,txt存储的只能是文本,对象序列化的结果是一个序列化文件,是一个文件输出流的结果。
追问
序列化文件保存在哪,我想见识见识,保存在电脑的哪个角落里?我看看跟文本文件有啥不一样的
追答

import java.io.Serializable;


import java.io.*;


public class Cat implements Serializable {

private String name;


public Cat() {

this.name = "new cat";

}


public String getName() {

return this.name;

}


public void setName(String name) {

this.name = name;

}


public static void main(String[] args) {

Cat cat = new Cat();

try {

FileOutputStream fos = new FileOutputStream("catDemo.out"); //这就是你序列化文件的存储位置,是由自己控制的

ObjectOutputStream oos = new ObjectOutputStream(fos);

System.out.println(" 1> " + cat.getName());

cat.setName("My Cat");

oos.writeObject(cat);

oos.close();

}

catch (Exception ex) {

ex.printStackTrace();

}

try {

FileInputStream fis = new FileInputStream("catDemo.out");

ObjectInputStream ois = new ObjectInputStream(fis);

cat = (Cat) ois.readObject();

System.out.println(" 2> " + cat.getName());

ois.close();

}

catch (Exception ex) {

ex.printStackTrace();

}

}

}


输出内容:


很抱歉,回答者上传的附件已失效
追问
原来.out文件就是序列化后的文件啊,那保存的购物信息记录也全在这里面吗?如果是在这里,那这个文件不是.txt格式的,打开看肯定是乱码?

如果信息记录没在out文件里,那应该在指定一个路径保存为.txt文件格式吧?这个就是能打开看的信息记录?

这俩文件是分开的 还是合在一起的?
追答
保存的购物信息都在catDemo.out中,但你是看不懂的,要JAVA虚拟机才能看懂,因为序列化文件本身不是为人类阅读准备的。

如果你想输出为txt,需要你在程序中手动指定输出的内容和格式,这样你才能够看懂。

不是两个文件,也可能是多个文件,你想生成多少文件就生成多少文件。
追问
那在问下,如果我也想保存输出为txt格式的。在程序中手动添加一个路径为:购物信息.txt就行了是吗?那你上面的那个catDemo.out不用删掉继续保留?

这样在电脑里就会产生一个是catDemo.out文件,一个是文本格式的购物信息.txt?
catDemo.out已经是序列化保存了一次了,后面再输出的.txt不需要序列化了,直接输出字符流保存到电脑里即可?因为前面已经有一个序列化了
追答
对的,你可以这样理解。

另外你是否需要序列化看你自己的需求,序列化是为了程序读取方便,没有必要非得输出的。
追问
意思就是说,你要不序列化也行,就是程序读取不方便,而且以前在内存里的对象结构全都没有了?
上面那个还要问下,其实在catDemo.out文件里只包含对象信息,应该也包含字符串信息吧?就是应该也包含txt里面的购物信息,而我输出txt格式,只是从catDemo.out文件里提取出字符串部分的信息给用户看而已,实际对象内容还在catDemo.out里保存?
追答

序列化是一种操作,你做序列化不是必要的,你做序列化是因为你想保存这个对象在文件系统上。


想象一种场景:

你开发了一个游戏,游戏里有人物,人物里有个属性时他现在拥有的金钱,当用户玩到一半选择保存游戏时,你有两个方案:

  1. 保存用户的金钱到txt中,下次加载游戏的时候,再从txt中读取金钱,让用户接着玩。

  2. 进行对象序列化,把对象存到文件系统上,下次可以玩的时候使用反序列化加载。

但是第一种方案有个缺点,用户如果知道了txt中保存着金钱,就可以自己把金钱改成99999,采用对象序列化方式就不会了。


最后一个,你没有理解JAVA中的对象,对象是在内存中保存的,它不会因为你序列化了之后它就不存在了,序列化等于把对象的数据复制了一份,序列化,然后输出到文件系统,真正的对象还是在程序中的。


就像你玩游戏玩到一半,突然想存个档,然后就把对象序列化了,但是游戏还在继续啊,里面的人物也没死啊,说明人这个对象还是在内存中存在的。


are we clear?

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值