00:02
好了,那么这些呢,我全部都给它关掉,各位啊,全部关掉那差不多我们这块也快讲完了啊,但是最后有一项我们得说明白,就是刚才那个疑问。是不是啊,刚才那个疑问啊,咱们再把这个叫object什么,嗯,Input stream和object out再打开啊,TEST01各位啊,看好了,打开input stream test1啊打好大家看这是不是那个学生类对吧?然后呢,这个地方有个什么,有一个负责序列化的。这个地方这个类呢,是负责什么反序列化的,我们再来一次啊,再来一次。来序列化一下。把这个111和这个name等于张三的这个学生对象放到文件里边,然后通过怎么着啊,反序列化走一个,我们看看能不能把这个学生对象拿出来,能吗?能是不是好了,各位啊,我问大家一个问题啊。就是说。假如说你这个类啊,是在是在十年前开发的。
01:05
现在是2020年。啊,那么2020年来了之后呢,这个类啊可能啊。怎么着呢?可能需要修改代码。听明白了吗?什么意思?这个业务可能发生改变了。就这个student这个类啊,它可能需要怎么着。需要改变代码。那么大家思考一下,你在十年前的时候,是不是曾经执行过一个object output stream,把一个学生对象是不是放到了一个文件当中?但你这是什么时候的操作呀,是十年前的操作呀。但你十年之后呢,你可能把这个STEM这个类改了,听懂了吗。可能改代码了,你比如在这加了个代码改了啊,那么改了之后大家想一想,现在改完Java源代码就是后期啊,就是过了很久student这个类。
02:06
源代码改动了,源代码改动之后需要重新编译。编译之后生成了全新的什么?生成了全新的什么?字节码文件。并且注意听啊,并且。Class文件。Class文件啊。再次运行的时候,Java虚拟机生成的序列化版本号。也会发生相应的什么改变,注意听啊,主要是这它这个类实现这个szable这个接口。
03:08
实际上是Java虚拟机看到这个类,实现这个接口之后,它会为这个类专门生成一个虚拟化版本号。但是你十年前是一序列化版本号,你十年后呢,你再去改变这个程序,那么这个时候会重新编译,再重新运行,会生成一个新的序列化版本号,这个时候如果两次序列化版号不一样。大家看一看它会不会出问题。已经重新编译了啊,不要再序列化了,各位啊,你需要这个时候,因为现在你是不是刚才已经序列化一次了。序列化的时候是不是十年前?你现在是不是改了这个类,加了代码重新编译,那么你再去运行的时候,大家看啊,再运行啊,看这个反序列化会不会出问题。来,走一个。嗯。好,出问题了,那出问题之后呢,我们把这个异常信息拿过来,我们分析一下。
04:02
分析一下各位啊,拿过来,拿过来之后呢,我们放到什么地方呢?哎,我们放到这个位置上,呃,放到这儿吧。啊。我们分析一下来翻译一下啊各位。好,他说叫做无效的类异常。对吧,说com.b power no Java b下边有个student这个类。他说你流里边的序列化。版本号。是这个值。但是你本地的local的class序列化版本号是这个值。
05:04
什么意思?这个是十年前,这是十年后。明白吧,序列化版本号发生了变动。看见了吧,它是不是就没有办法再反序列化了?你看这个input在序列的问题。看。是吧?那么大家想一想,序列化版本号有什么用啊?你这个累。十年前,序列化进去。你这个类改了呀,重新编译生成了新的class文件呀。那么这个时候你在反序列化的时候就出问题了。
06:02
出现一个什么问题啊,叫序列化版本号不一致。对吧。那么大家思考一下,这个序列化板块有什么用啊?有同学这里真的会有序列化版本号吗?有,为什么这里会有序列化版本号啊?因为你实现了这个接口。所以实现这个标志性接口的作用,我再强调一下,各位Java虚拟机看到sir LA接口之后,会自动生成一个序列化版本号。啊,这里没有手动写出来,Java虚拟机会默认提供一个序列化版本号。明白吧,会默认在这里提供一个序列化版本号的,你只不过看不见。对吧,哎,你在执行你看。不行,反去拉不了。对吧,哎,所以序列化斑块是干什么用的各位。想好了吗?
07:00
Java语言中是采用什么机制来区分?是采用什么机制来区分类的?第一,首先通过什么呀类名进行进行什么比对。首先通过类名进行比对啊,如果类名不一样,肯定不是同一个类。第二,如果类名一样对吧,如果类名一样怎么。再怎么进行类的区分?靠什么呀,序列化什么版本号进行区分。啊,如果类名一样,再怎么进行区分,再怎么进行类的区分啊,是靠序列化版本号进行区分的。你明白吧,那你看。
08:02
对吧。是不是,哎,是这样的,好了,那么现在我问大家一个问题啊。有没有可能出现这种问题?什么问题呢?就是确实是十年前写的这个类,十年后我确实是在原先那个类上改了代码。有没有这个可能,各位大家思考一下。思考一下。序列化版本号是防什么的各位?有没有咱们班的同学写了一个类,也叫com bde Java bin?我给大家举个例子,我不知道大家有没有听懂啊,这序列化版本号到底是干啥的?是用来区分类的,你懂吗?这个小鹏啊。编写了一个类。
09:01
就是这个类。这个胡浪同学呀。也编写了一个类,也叫这个名儿。有没有可能不同的人开发了或者编写了同一个类?但这两个确实不是同一个类。有点懵吧,确实是因为这一个小鹏写胡浪写的是不是,哎,这两个类。确实不是同一个类。这个时候序列化版本号。就起上作用了。对吧,哎,起上作用了,对于什么呀,Java虚拟机来说,Java虚拟机是可以区分开这两个类的。
10:16
因为这两个类都实现了什么stereo,什么liable接口都有什么呀,默认的什么序列化版本号,它们的序列化版本号不一样,所以区分开了。你明白什么意思吧,Able。There liable。这就是实现这个序列化接口的一个作用,我说了这个作用是用来起到标识标记的作用,当你这个类实现了这个接口,Java虚拟机一定会给你这个类生成一个序列版本号。
11:05
就算你这两个类写的类名是一模一样的,对不起,加马逊机也认为你是两个不同的类。这个序列化版本号就是用来区分类的各位。这是虚列化版本号的一个好处,对吧。这是不是序列化版本号的一个好处啊,对吧?哎,这是序列化版本号的好处,什么好处啊,这是序列化版本号,这是自动啊,这是自动生成序列化版本号的好处,那我问大家一个问题啊。请思考。这种自动生成序列化版本号有什么缺陷?这种自动生成序列化版本号有什么缺陷?思考一下。就这种自动生成序列化斑块有什么缺陷?
12:02
有没有可能你这个类是十年前和十年后的关系,十年前是这样的一个类,十年后改的这个类,但是我问你十年前和十年后这个类是不是还是同一个类?后续不能修改代码,对,有道理。就这种自动的序列化版本号,自动生成序列化版本号有什么缺陷呀。就是缺陷,就是你不能改代码,你只要一改代码就废了这个代码,你只要一改,那十年前序列化进去的这个数据都没有办法反序列化了,听懂了吗?所以这是自动生成序列化版本号的一个缺陷。我不知道大家有没有理解这个东西啊,序列化版本号有什么用?各位序列化版本号是用来区分类的。因为你这个类实现了这个接口,所以它会自动生成序列化版本号,你这个类和这个类也实现了这个接口,所以你自动生成序列版本号,你这个版本号不一样,Java虚拟机就能区分开你这两个类。
13:04
能区分开你这两个类,但是这种自动生成的这种序列化版本号有什么有什么问题,它的问题在于你十年前假如说你确实是这个类,然后你写的代码,十年之后你改代码改了,改完之后它重新编译,那由于它会生成一个新的序列化版本,导致前后这个类啊不一致了,它不是同一个类了,但我问你从业务逻辑角度出发,你十年前是这个类,你十年后直播改了代码,你十年后这个类是不是还是十年前那个类还是一样的,得得是同一个类吧。对吧,你看所以说自动生成序列化版本号啊,是有缺陷的。它的缺陷这个研标书的太好了,就是缺陷就是这种请思考对吧,这种自动生成序列化版本有什么缺陷,就是就是代码不能改。啊,一旦这种自动生成的序列化。版本号,缺点是一旦一旦啊。
14:02
一旦什么呀,代码确定之后,不能进行后续的修改,因为什么呀,因为只要怎么着修改。必然会重新编译。此时会生成全新的序列化版本号。这个时候,Java虚拟机会认为这是一个全新的类。这样就不好了,明白吗?哎,注意听啊,眼标眼标啊,注意听啊注意听,所以我们不建议自动生成序列化版本号,听明白了吗?建议把序列化版本号固定死。注意啊。最终结论,凡是一个类实现了什么sterezable接口建议啊,给该类提供一个固定不变的序列化版本号啊,凡是一个类实现了接口。
15:21
建议给该类提供一个固定不变的序列化版本号。这样。以后这个类即使代码修改了,但是版本号不变,Java虚机会Java虚拟机会认为是同一个类,明白吧,所以这块呢,我们要手动的给他写出来,各位啊,我们模仿一下这个list,看list怎么写的行吧,来,我们点过去看一下list啊,加va u list,嗯,走过去。A released,好,大家看这里有一个序列号,版本号,看见了吗?Or list是不是实现了这个接口啊,这个位置是不是把序列化版本号定下来了,以八六开始,以八九结尾,这么这么长一串的一个数字定下来,各位啊,我们给它放到这儿。
16:13
建议将序列化版本号手动的写出来。不建议自动生成,你给他写出来啊,这个编号最好是全球唯一,不重复啊。最好是全球唯一,不重复。各位。它一旦出生,从他出生到最后,到最后死亡,整个过程,这个类的序列化斑块永远都是这个值。对同一个项目来说,你写上一呀,写上二呀,写上三呀都没问题啊,你正常写就行了啊,正常写就行了。明白吧,哎,因为我说了,首先区分一个类是靠什么区分各位。是靠类区分,听懂了吗?先靠类名区分,只有类名相同的情况下,才会考虑使用版本号进行区分。
17:03
听懂了吗?所以这个冲突的概率很低啊,冲突的概率很低啊,Java虚拟机虚拟机。识别一个类的时候通过什么?先通过类名,然后就是如果类名一致,再通过什么序列化版本号。注意啊,它是个常量,看见没有private static,私有静态的一个常量,Long类型the version u ID叫序列化版本号,我写EL。就行了。大家看啊,有没有源代码,大家现在越来越能看懂了。好。这个string这个类有没有序列化able往下走,我们找找大家看有没有啊。
18:00
是不是有啊,大家看他说use s version u from jdk 1.0.2。什么意思啊,翻译一下,翻译一下这句话什么意思。他说,自从JDK1.0.2开始,这个序列化板块就一直在用这个号。这个号没变。听懂了吗?这个号自出生到现在就没变过,也不能变,大家想想JDK有没有升级?JDK有没有升级,你告诉我各位a release这个东西后来有没有升级,这个代码有没有改?思考一下。集合有没有升级哈西集合?有没有后期改代码?改代码也不影响。
19:01
是吧,哎也不影响,因为什么呀,序列化版本号没变。听明白了吗?来我们加这个序列化板块,看看还有没有问题啊,来我们序列化一下各位啊,序列化一个学生进去等于111张三,我们给他放到文件里边序列化。好,接下来大家注意了啊,我们把这个类改了,各位改了啊,来加一个麦啊。来再加一个什么address,好,这个类改没改,代码改没改,保存了各位啊,这个重新编译的吧,但是序列把写一写还是一吧,好,我们反序列化一下啊,反序列化一下各位object因input反序列化一下啊,看这个学生能不能回来,来点右键我们执行一下,改代码也没问题,看学生是不是照样能够反序列化回来啊。正常吧,所以这就没问题了,这就没问题,所以说建议怎么着啊,哎,我们这个累啊。
20:00
手动的把序列化版本出来。听明白了吗?各位收到的话扣一。收到扣一啊,收到扣一各位。就是说我们参与序列化和反序列化的都得实现这个接口。并且建议大家把序列化版本号手动的写出来。手动的写出来啊,手写出来。不手动写,有的时候是不是也没问题,不手动写是不是有的时候也没问题,各位。就不手动写。不手动写我们的,如果这个类没有改的话,是不是没问题。啊。如果这个类没有发生任何改动的话,是不是没有任何问题啊。对吧,大家想一想。
21:01
呃,如果name属性删了,是不是就不能接受这个信息了,来我们再改一下,把name删了行不行,哎,删了,然后然后这个name删了之后呢,这边代码我们要改动一下啊,这注释掉改代码来看看能不能回来啊。他们回来。来。好了,那么接下来我们回来一下啊,看能不能回来走。行不行啊。来,那这个name是啥?没有name了,各位,里边就没有name了,没问题。还可以回来你看。改了吧,是不还可以回来啊,正常回来,各位啊,正常回来。就只不过没有内部属性了,没问题啊,没问题,所以你只要有序列化版本号就行,你只要有序列化版本号就可以。
22:06
啊,所以呢,咱们今天呢,在这讲这个序列化和反序列化的时候,这块啊,咱们耗费的时间比较长,这个呢,其实比较难以理解,就是说有很多程序员他不太理解,诶我为什么要去实现这个接口啊,告诉大家啊,因为一个类实现这个接口了,Java虚拟机,Java虚机会为这个类自动生成一个序列化版本号。啊,那为什么生成序列化版本号啊,是用来区分什么的,我在这讲的很清楚,是用来区分类的,我说小朋友和胡浪呢,都写了这样一个类,都实现了这个接口,类名一样,但是它序列化版本不同,所以呢,Java虚拟机要依靠这个序列版块来区分这个类嘛。但是有没有可能是同一个类在十年前和十年后改了代码,有这个可能,改了代码重新编译生成序列,序列化版本号也有问题啊,对吧?那之前十年前序列化进去的东西,在十年后在反序列化的时候不就出问题了吗?对吧?所以这边呢,诶建议手动的把序列化版牌写上去,这样的话,即使你后期再改动的时候,对吧,再改动代码也没关系,认为Java虚拟机第一个靠类名区分,类名如果相同的情况下,再靠序列化版本号进行区分,类名一样,并且序列化版本一样的话,Java虚拟机就会认为这是同一个类,然后它就会给你反序列化啊,就会给你反序列化是这样的啊。
23:23
好了,那这样的话,Object input stream和object out stream它的原理啊,深层次的原理咱们就讲完了,各位啊,有一个很重要的这个结论,这个结论的话,我觉得也得再重复写一下啊,这个结论凡是一个类实现了sir lab接口,建议给类,给该类提供一个固定不变的虚拟化版本号,这样以后这个类及时代码修改了,但是版本号不变,Java虚拟机会认为是同一个类啊,同一个类。
我来说两句