当前位置: 首页 > 后端技术 > Java

基于JAVA的序列化

时间:2023-04-01 22:24:21 Java

今天我们就来说说Serializable接口的序列化和反序列化。没有方法。实现该接口表示ObjectOutputStream可以序列化和反序列化,Object可以序列化为流objectInputStream。当序列化转为对象序列化时,会计算一个Serial版本唯一标识符来标识类(安全哈希值),并将哈希值存储在流中,java在反序列化时再次计算类标识值(如果定义了class类发生了变化,值也会发生变化),将新计算的值与从流中取出的值进行比较,如果不一致,则说明该类的序列化版本与我们兼容的当前类定义不同。将生成InvalidClassException。publicclassBankAccountimplementsSerializable{privateStringid;私人int余额=0;publicBankAccount(Stringid){this.id=id;}publicBankAccount(Stringid,intstartBalance){this.id=id;余额=开始余额;}publicStringgetId(){返回id;}publicsynchronizedintgetBalance(){返回余额;}publicsynchronizedvoiddeposit(intamount){balance+=amount;}publicsynchronizedvoidwithdrawal(intamount){balance-=amount;}}序列化与反序列化方法publicclassMain{publicstaticvoidmain(String[]args){BankAccountba=newBankAccount("10",500);ba.存款(250);saveAccount(ba,"/Users/buxuesong/Documents/svn_code/demo/account.dat");BankAccountbb=loadAccount("/Users/buxuesong/Documents/svn_code/demo/account.dat");System.out.println(bb.getId()+"|"+bb.getBalance());}私有静态voidsaveAccount(BankAccountba,StringfileName){try(ObjectOutputStreamos=newObjectOutputStream(Files.newOutputStream(Paths.get(fileName)))){os.writeObject(ba);}catch(Exceptione){System.out。println(e.getSuppressed()+"|"+e.getMessage());}}privatestaticBankAccountloadAccount(StringfileName){BankAccountba=null;try(ObjectInputStreamoi=newObjectInputStream(Files.newInputStream(Paths.get(fileName)))){ba=(BankAccount)oi.readObject();}catch(Exceptione){System.out.println(e.getSuppressed()+"|"+e.getMessage());}返回ba;}}输出10|750当类的定义字段发生变化时,与原来序列化的唯一标识不同,导致无法反序列化,这就需要自定义serialVersionUID,如果以后修改类也可以反推序列化,新增字段默认值为空或原默认值(0为int)privatestaticfinallongserialVersionUID=-23324324324L;还可以自定义序列化和反序列化方法,privateinBankAccountvoidwriteObject(ObjectOutputStreamout)throwsIOException{out.defaultWriteObject();}privatevoidreadObject(ObjectInputStreamin)throwsIOException,ClassNotFoundException{ObjectInputStream.GetFieldfields=in.readFields();id=(String)fields.get("id",null);balance=fields.get("余额",0);lastTxType=fields.get("lastTxType",'u');lastTxAmount=fields.get("lastTxAmount",-1);}执行方法BankAccountbb=loadAccount("/Users/buxuesong/Documents/svn_code/demo/account.dat");System.out.println(bb.getId()+"|"+bb.getBalance()+"|"+bb.getLastTxType()+"|"+bb.getLastTxAmount());输出10|750|你|-1还可以对一些需要transient修改的字段进行序列化,可以通过其他方式检索,节省了序列化的时间。具体如下publicclassAccountGroupimplementsSerializable{privatestaticfinallongserialVersionUID=106962907155393149L;privateMapaccountMap=newHashMap();私有瞬态inttotalBalance;publicintgetTotalBalance(){返回总余额;}publicvoidaddAccount(BankAccountaccount){totalBalance+=account.getBalance();accountMap.put(account.getId(),账户);}privatevoidreadObject(ObjectInputStreamin)throwsIOException,ClassNotFoundException{in.defaultReadObject();for(BankAccountaccount:accountMap.values())totalBalance+=account.getBalance();}}执行方法中的存储到流以及从流中取回的方法privatestaticvoidsaveGroup(AccountGroupg,StringfileName){try(ObjectOutputStreamos=newObjectOutputStream(Files.newOutputStream(Paths.get(fileName)))){os.writeObject(g);}catch(Exceptione){System.out.println(e.getSuppressed()+"|"+e.getMessage());}}privatestaticAccountGrouploadGroup(StringfileName){AccountGroupg=null;try(ObjectInputStreamoi=newObjectInputStream(Files.newInputStream(Paths.get(fileName)))){g=(AccountGroup)oi.readObject();}catch(Exceptione){System.out.println(e.getSuppressed()+"|"+e.getMessage());}returng;}执行方法:BankAccountacct1=newBankAccount("1234",500);BankAccountacct2=newBankAccount("9866",750);AccountGroupgroup=newAccountGroup();group.addAccount(acct1);group.addAccount(acct2);saveGroup(group,"/Users/buxuesong/Documents/svn_code/demo/group.dat");AccountGroupgroup2=loadGroup("/Users/buxuesong/Documents/svn_code/demo/group.dat");System.out.println("group2.getTotalBalance:"+group2.getTotalBalance());Outputgroup2.getTotalBalance:1250其他序列化方法,实现Externalizable接口voidwriteExternal(ObjectOutputout);voidreadExternal(ObjectInputin);