Skip to content

Instantly share code, notes, and snippets.

@rupert-ong
Created September 17, 2018 19:24
Show Gist options
  • Save rupert-ong/b4dbae87302e13be20e8d406480b85aa to your computer and use it in GitHub Desktop.
Save rupert-ong/b4dbae87302e13be20e8d406480b85aa to your computer and use it in GitHub Desktop.
Java Serialization, Deserialization and Transient Fields #java #serialization #deserialization #transient #objectoutputstream #objectinputstream
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Used to illustrate transient (don't get serialized) fields.
* Useful for values that are derived from other members, like totals.
* For deserialization, you must specify the value for transient fields in the readObject method
*/
public class AccountGroup implements Serializable {
private static final long serialVersionUID = -7665535201427596893L;
private Map<String, BankAccount> accountMap = new HashMap<>();
private transient int totalBalance;
public int getTotalBalance() { return totalBalance; }
public void addAccount(BankAccount acct) {
totalBalance += acct.getBalance();
accountMap.put(acct.getId(), acct);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
// Return default values for other fields
in.defaultReadObject();
// Set value for totalBalance by deriving it from hash map
for(BankAccount acct : accountMap.values())
totalBalance += acct.getBalance();
}
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class BankAccount implements Serializable {
// Type serialver -show in cmd prompt of output directory to get serialUID
// serialVersionUID used to identify and maintain (backwards) compatibility
// when updating this file when deserializing
private static final long serialVersionUID = 690408737872309788L;
private String id;
private int balance;
private char lastTxType;
private int lastTxAmount;
public BankAccount(String id) {
this.id = id;
}
public BankAccount(String id, int balance) {
this.id = id;
this.balance = balance;
}
public String getId(){
return this.id;
}
public synchronized int getBalance(){
return this.balance;
}
public synchronized void deposit(int amt) {
this.balance += amt;
this.lastTxAmount = 'd';
this.lastTxAmount = amt;
}
public synchronized void withdraw(int amt) {
this.balance -= amt;
this.lastTxAmount = 'w';
this.lastTxAmount = amt;
}
// Use custom serialization and deserialization to determine what we
// want to write and have returned in instances where BankAccount changes
// and we do not want to return default member values, which may be misleading.
// In the case of lastTxAmount and lastTxType, default returns of 0 and null
// are misleading, as it implies no recent transactions took place (if we changed
// BankAccount to include those members after having serialized an earlier, simpler version
// with only id and balance in it)
/**
* Use by serialize process, specify to use the default serialization (example)
* @param out ObjectOutputStream
* @throws IOException
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
}
/**
* Used by deserialize process to extract fields for our class type
* @param in ObjectInputStream
* @throws IOException
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField fields = in.readFields();
// Determine the default values to return in the case no value is found...
id = (String) fields.get("id", null);
balance = fields.get("balance", 0);
lastTxType = fields.get("lastTxType", 'u');
lastTxAmount = fields.get("lastTxAmount", -1);
}
}
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main {
public static void main(String[] args) {
// serializeBankAccount();
// deserialzeBankAccount();
// serializeTransientExample();
deserializeTransientExample();
}
private static void serializeTransientExample() {
BankAccount acct1 = new BankAccount("1234", 500);
BankAccount acct2 = new BankAccount("9876", 750);
AccountGroup group = new AccountGroup();
group.addAccount(acct1);
group.addAccount(acct2);
saveGroup(group, "group.dat");
}
private static void deserializeTransientExample() {
AccountGroup group = loadGroup("group.dat");
System.out.println("Total balance: " + group.getTotalBalance());
}
private static void deserialzeBankAccount() {
BankAccount ba = loadAccount("account.dat");
System.out.println("Deserialized BankAccount: " + ba.getBalance());
}
private static void serializeBankAccount() {
BankAccount acct = new BankAccount("1234", 500);
acct.deposit(50);
saveAccount(acct, "account.dat");
}
/**
* Serialize BankAccount by writing it into a file using ObjectOutputStream
*
* @param ba BankAccount type instance
* @param filename Filename to write serialized object into
*/
private static void saveAccount(BankAccount ba, String filename) {
try (ObjectOutputStream objectStream = new ObjectOutputStream(Files.newOutputStream(Paths.get(filename)))) {
objectStream.writeObject(ba);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Deserialize BankAccount by reading it from a file using ObjectInputStream
*
* @param filename Filename to deserialize object from
* @return BankAccount type instance
*/
private static BankAccount loadAccount(String filename) {
BankAccount ba = null;
try (ObjectInputStream objectStream = new ObjectInputStream(Files.newInputStream(Paths.get(filename)))) {
ba = (BankAccount) objectStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return ba;
}
/**
* Serialize AccountGroup
*
* @param group AccountGroup
* @param filename Filename to serialize object into
*/
private static void saveGroup(AccountGroup group, String filename) {
try (ObjectOutputStream objectStream =
new ObjectOutputStream(Files.newOutputStream(Paths.get(filename)))) {
objectStream.writeObject(group);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Deserialize Account Group
*
* @param filename Filename to deserialize object from
* @return AccountGroup
*/
private static AccountGroup loadGroup(String filename) {
AccountGroup g = null;
try (ObjectInputStream objectStream =
new ObjectInputStream(Files.newInputStream(Paths.get(filename)))) {
g = (AccountGroup) objectStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return g;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment