关于java class 版本的兼容问题

本文详细探讨了Java class版本兼容问题,尤其是序列化时遇到的挑战。核心在于serialVersionUID字段,其在不同版本间的不一致会导致不兼容异常。解决方法是显式设置相同serialVersionUID以确保兼容。当类的结构如名字、域、方法或接口等发生变化时,系统会自动生成不同的serialVersionUID。反序列化时,只有存在于两个版本中的域会被恢复,新出现或缺失的域则会被处理。通过实例展示了如何进行序列化和反序列化操作。

 关于java class 版本的兼容问题

A   
  总的来说:
   因为序列化自动生成的UID要求严格,一个很小的改动就认为是不同的class,自己设置这个用来强制系统认为这两个不完全相同的类是同一个,就是  两个版本兼容
   serialVersionUID 域是不同版本间兼容的标记,SerialVersionUID不同,发生了什么?  
  不兼容版本的异常被抛出 
B   
  解决问题:版本兼容性
采用显式声明 serialVersionUID 并且保证需要兼容的class 拥有相同的 serialVersionUID 。
格式:private static final long serialVersionUID = -5288121327143580980L;
C   
  隐式 serialVersionUID 的特性:
同一个类的不兼容版本有不同的 serialVersionUID 
如果您不提供一个值,将回自动产生一个 
生成的值是基于类的"形状"
●类的名字。 
●域的名字。 
●方法的名字。 
●已实现的接口。 
改动上述任意一项内容(无论是增加或删除),都会引起编码值变化,从而引起类似的异常警报
D    :)
  具体的情况下的兼容:
o        如果值匹配,反序列化过程将为存在的域尽量提供值 
o        只有同时存在于两个版本的域才会被恢复 
        当前版本所没有的域被忽略 
        当前版本新出现的域被置空 

E    :)
  下面用一个例子说明问题:
1、        带能参数的构造函数初始化对象
2、        Writeobj()将当前对象写入test.txt 文件中
3、        Readobj()将test.txt文件中的对象读出来
4、        Printout()将对象及其值打印出来

  1.  
  2. package ser;
  3.  
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8. import java.io.ObjectInputStream;
  9. import java.io.ObjectOutputStream;
  10. import java.io.Serializable;
  11.  
  12. public  class test  implements  Serializable   {
  13.  
  14.          private  static  final  long serialVersionUID = -5288121327143580980L;
  15.  
  16.          //default 
  17.          private  int a ;
  18.  
  19.          public  char b ;
  20.  
  21. //        protected long c ;
  22.  
  23.          public test ( )  {
  24.                  super ( );
  25.                  // TODO Auto-generated constructor stub
  26.          }
  27.  
  28.          public test ( int at,  char bt,  long ct )  {
  29.                  //initial
  30.                  this. a = at;
  31.                  this. b = bt;
  32. //                this.c = ct;
  33.          }
  34.  
  35.          public  void printout ( )  {
  36.                  //print the object member
  37.                  System. out. println ( "/nthis is the object members :/n" );
  38.                  System. out. println ( "a = " + a +  "/n" );
  39.                  System. out. println ( "b = " + b +  "/n" );
  40. //                System.out.println("c = " + c + "/n");
  41.          }
  42.  
  43.          public  void writeobj ( )  {
  44.                  ObjectOutputStream out;
  45.                  try  {
  46.                         out =  new  ObjectOutputStream ( new  FileOutputStream ( "test.txt" ) );
  47.                         
  48.                         out. writeObject ( this );
  49.                         out. close ( )// Also flushes output
  50.                  }  catch  ( FileNotFoundException e )  {
  51.                          // TODO Auto-generated catch block
  52.                         e. printStackTrace ( );
  53.                  }  catch  ( IOException e )  {
  54.                          // TODO Auto-generated catch block
  55.                         e. printStackTrace ( );
  56.                  }
  57.  
  58.          }
  59.  
  60.          public  static  void readobj ( )  throws  ClassNotFoundException  {
  61.                  ObjectInputStream in;
  62.                  try  {
  63.                         in =  new  ObjectInputStream ( new  FileInputStream ( "test.txt" ) );                
  64.                         test tr =  (test ) in. readObject ( );                
  65.                         tr. printout ( );                        
  66.                         in. close ( );
  67.                  }  catch  ( FileNotFoundException e )  {
  68.                          // TODO Auto-generated catch block
  69.                         e. printStackTrace ( );
  70.                  }  catch  ( IOException e )  {
  71.                          // TODO Auto-generated catch block
  72.                         e. printStackTrace ( );
  73.                  }
  74.  
  75.          }
  76.  
  77.          /**
  78.          * @param args
  79.          */
  80.          public  static  void main ( String [ ] args )  {
  81.                  // TODO Auto-generated method stub                
  82.                 test tst =  new test ( 206'a', 112233445566L );                
  83.                 tst. writeobj ( );
  84.                  try  {                        
  85.                         readobj ( );
  86.                  }  catch  ( ClassNotFoundException e )  {
  87.                          // TODO Auto-generated catch block
  88.                         e. printStackTrace ( );
  89.                  }
  90.  
  91.          }
  92.  
  93. } 
  94.  
Parsed in 0.594 seconds,  using GeSHi 1.0.7.13

F    :)
1、        执行程序,a和b正常写入,查看文件
2、        将tst.writeobj()注释掉,执行,正常读出对象,然后再改变SerialVersionUID的值,执行,抛出异常:java.io.InvalidClassException,这说明了:“serialVersionUID 域是不同版本间兼容的标记”
现在我们再将serialVersionUID改回原值,将//        protected long c ; 及下面有关变量c的注释打开,此时同样是注释掉tst.writeojb(),不写文件。这个升了级的类中增加了一个成员,执行读老版本类写的文件,我们可以看到: c = 0 这说明了:“在serialVersionUID保证版本兼容的同时,当前版本新出现的域被置空”
3、“当前版本所没有的域被忽略 ”可以用写a、b、c三个成员,读其中的两个成员的方法验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值