明天来讲讲序列化以及反序列化

Serializable接口,没有method,实现该接口表明能够序列化以及反序列化
ObjectOutputStream,将Object序列化为stream流
ObjectInputStream,通过stream流反序列化转化为Object
序列化时,计算出一个Serial version unique identifier标识这个class(平安的哈希值),并将这个哈希值其存储到stream中,而反序列化时java再次计算这个class的标识值(如果class类的定义已扭转则值也会发生变化),新计算的值与从stream取出来的值做比拟,如果不统一,示意该类的序列化版本与咱们领有的以后类定义不兼容。会产生InvalidClassException。

public class BankAccount implements Serializable {    private String id;    private int balance = 0;    public BankAccount(String id){        this.id = id;    }    public BankAccount(String id, int startBalance){        this.id = id;        balance = startBalance;    }    public String getId(){        return id;    }    public synchronized int getBalance(){        return balance;    }    public synchronized void deposit(int amount){        balance += amount;    }    public synchronized void withdrawal(int amount){        balance -= amount;    }}

序列化与反序列化办法

public class Main {    public static void main(String[] args) {        BankAccount ba = new BankAccount("10",500);        ba.deposit(250);        saveAccount(ba,"/Users/buxuesong/Documents/svn_code/demo/account.dat");        BankAccount bb = loadAccount("/Users/buxuesong/Documents/svn_code/demo/account.dat");        System.out.println(bb.getId() +" | " + bb.getBalance());    }    private static void saveAccount(BankAccount ba, String fileName){        try(ObjectOutputStream os = new ObjectOutputStream(Files.newOutputStream(Paths.get(fileName)))){            os.writeObject(ba);        }catch(Exception e){            System.out.println(e.getSuppressed() +" | "+ e.getMessage());        }    }    private static BankAccount loadAccount(String fileName){        BankAccount ba = null;        try(ObjectInputStream oi = new ObjectInputStream(Files.newInputStream(Paths.get(fileName)))){            ba = (BankAccount) oi.readObject();        }catch(Exception e){            System.out.println(e.getSuppressed() +" | "+ e.getMessage());        }        return ba;    }}输入10 | 750

当扭转了class的定义字段后,与原有序列化的惟一标识不同,导致无奈反序列化,这就须要自定义serialVersionUID,当前批改了该类,也会能够反序列化回来,只是新增的字段默认值为空或者是原始默认值(int的话就是0)

private static final long serialVersionUID = -23324324324L;

还能够自定义序列化以及反序列化的办法,在BankAccount中

private void writeObject(ObjectOutputStream out) throws IOException {    out.defaultWriteObject();}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{    ObjectInputStream.GetField fields = in.readFields();    id = (String) fields.get("id",null);    balance = fields.get("balance",0);    lastTxType = fields.get("lastTxType",'u');    lastTxAmount = fields.get("lastTxAmount",-1);}

执行办法

BankAccount bb = loadAccount("/Users/buxuesong/Documents/svn_code/demo/account.dat");System.out.println(bb.getId() +" | " + bb.getBalance()+" | " +bb.getLastTxType()+" | "+bb.getLastTxAmount());输入10 | 750 | u | -1

还能够针对某些字段不必须做序列化解决,须要通过transient润饰该字段,能够通过其它形式获取回来,这样节俭了序列化的工夫
具体如下

public class AccountGroup implements Serializable {    private static final long serialVersionUID = 106962907155393149L;    private Map<String, BankAccount> accountMap = new HashMap();    private transient int totalBalance;    public int getTotalBalance(){        return totalBalance;    }    public void addAccount(BankAccount account){        totalBalance += account.getBalance();        accountMap.put(account.getId(), account);    }    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {        in.defaultReadObject();        for(BankAccount account: accountMap.values())            totalBalance += account.getBalance();    }}

执行办法中的存储到流以及从流中取回的办法

private static void saveGroup(AccountGroup g, String fileName){    try(ObjectOutputStream os = new ObjectOutputStream(Files.newOutputStream(Paths.get(fileName)))){        os.writeObject(g);    }catch(Exception e){        System.out.println(e.getSuppressed() +" | "+ e.getMessage());    }}private static AccountGroup loadGroup(String fileName){    AccountGroup g = null;    try(ObjectInputStream oi = new ObjectInputStream(Files.newInputStream(Paths.get(fileName)))){        g = (AccountGroup) oi.readObject();    }catch(Exception e){        System.out.println(e.getSuppressed() +" | "+ e.getMessage());    }    return g;}

执行办法:

BankAccount acct1 = new BankAccount("1234", 500);BankAccount acct2 = new BankAccount("9866", 750);AccountGroup group = new AccountGroup();group.addAccount(acct1);group.addAccount(acct2);saveGroup(group, "/Users/buxuesong/Documents/svn_code/demo/group.dat");AccountGroup group2 = loadGroup("/Users/buxuesong/Documents/svn_code/demo/group.dat");System.out.println("group2.getTotalBalance:"+group2.getTotalBalance());

输入

group2.getTotalBalance:1250

其余序列化办法,实现Externalizable接口

void writeExternal(ObjectOutput out);void readExternal(ObjectInput in);