hz90 / java-base-knowledge

0 stars 0 forks source link

序列化和反序列化 #4

Open hz90 opened 5 years ago

hz90 commented 5 years ago

jdk1.8 此问题的由来,阅读ArrayList,源码发现transient Object[] elementData; 存数据的数组用transient 修饰 因为这个数组是ArrayList存数据的缓存数组,所以序列化时需要去除null值,节省时间和空间

序列化:把对象转换为字节流,以便在进程或者网络中传输,或者存储,也就是对象持久化。 反序列化:把字节流转换为对象 serialVersionUID :必须设置值,反序列化用, Transient 关键字使用,序列化会变为null;一般用于修饰敏感信息,静态变量不参与序列化,变量用Transient 修饰,不参见序列化

jdk api java.io.Serializable java.io.Externalizable ObjectOutput ObjectInput ObjectOutputStream ObjectInputStream

package com.xx;

import java.io.Serializable;

public class Account implements Serializable { private static final long serialVersionUID = 1L;

private  static String account_id;
private String account_no;
private String account_pass;
transient private String account_date;
public static int yoko = 10;
public Account() {
}

public String getAccount_id() {
    return account_id;
}

public void setAccount_id(String account_id) {
    this.account_id = account_id;
}

public String getAccount_no() {
    return account_no;
}

public void setAccount_no(String account_no) {
    this.account_no = account_no;
}

public String getAccount_pass() {
    return account_pass;
}

public void setAccount_pass(String account_pass) {
    this.account_pass = account_pass;
}

public String getAccount_date() {
    return account_date;
}

public void setAccount_date(String account_date) {
    this.account_date = account_date;
}

@Override
public String toString() {
    return yoko+"***"+this.account_id + this.account_no + this.account_pass + this.account_date;
}

}

package com.xx;

import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;

public class SerializableTool { public static void main(String[] args) throws Exception, IOException { Account account = new Account(); account.setAccount_id("000"); account.setAccount_no("111"); account.setAccount_pass("222"); account.setAccount_date("333"); System.out.println(account); String tmpname = "C:\pleiades4.9\pleiades\workspace\java8inaction\src\com\xx\account.tmp"; ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(tmpname)); oos.writeObject(account); oos.close(); // account.setAccount_id("4444"); Account.yoko=20; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(tmpname)); Account accountRead = (Account) ois.readObject(); System.out.println(accountRead); } } 10000111222333 20000111222null 对于静态变量,不参与序列化,静态变量属于类变量, transient 修饰的不会被序列化

Java另一个序列化接口java.io.Externalizable import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput;

public class AccountEx implements Externalizable { private static final long serialVersionUID = 1L;

private static String account_id;
private String account_no;
private String account_pass;
transient private String account_date;
public static int yoko = 10;

public AccountEx() {
}

public String getAccount_id() {
    return account_id;
}

public void setAccount_id(String account_id) {
    this.account_id = account_id;
}

public String getAccount_no() {
    return account_no;
}

public void setAccount_no(String account_no) {
    this.account_no = account_no;
}

public String getAccount_pass() {
    return account_pass;
}

public void setAccount_pass(String account_pass) {
    this.account_pass = account_pass;
}

public String getAccount_date() {
    return account_date;
}

public void setAccount_date(String account_date) {
    this.account_date = account_date;
}

@Override
public String toString() {
    return yoko + "***" + this.account_id + this.account_no + this.account_pass + this.account_date;
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(account_id);//000
    out.writeObject(account_no);//111
    out.writeObject(account_pass);//222
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    account_no=(String) in.readObject();
    account_pass=(String) in.readObject();
}

}


import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;

public class SerializableTool { public static void main(String[] args) throws Exception, IOException { AccountEx account = new AccountEx(); account.setAccount_id("000"); account.setAccount_no("111"); account.setAccount_pass("222"); account.setAccount_date("333"); System.out.println(account); String tmpname = "C:\pleiades4.9\pleiades\workspace\java8inaction\src\com\xx\account.tmp"; ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(tmpname)); oos.writeObject(account); oos.close(); // account.setAccountid("4444"); AccountEx.yoko=20; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(tmpname)); AccountEx accountRead = (AccountEx) ois.readObject(); System.out.println(accountRead); } } Externalizable继承了Serializable,序列化该类时,需要重写writeExternal()与readExternal(),write对象的顺序和read对象的顺利时一致的 10000111222333 20000000111null 如果被Transient 修饰也会被序列化____ 序列化的数据可以被签名和密封 通过使用 writeObject 和 readObject 可以实现密码加密和签名管理 如果需要对整个对象进行加密和签名,最简单的是将它放在一个 javax.crypto.SealedObject 和/或 java.security.SignedObject 包装器中。两者都是可序列化的,所以将对象包装在 SealedObject 中可以围绕原对象创建一种 “包装盒”。必须有对称密钥才能解密,而且密钥必须单独管理。同样,也可以将 SignedObject 用于数据验证,并且对称密钥也必须单独管理 来自:https://www.ibm.com/developerworks/cn/java/j-5things1/index.html