背景: 抽空整理一下.特此紀要!
問題:
1. transient是什麼?
2. transient關鍵字能做什麼?
3. transient底層實作原理是什麼?
解答:
1. transient是什麼?
transient是java中的一個關鍵字.
2. transient關鍵字能做什麼?
transient關鍵字用來修飾不需要序列化的對象屬性,當對象的某個屬性被transient關鍵字修飾後,序列化這個對象的時候,這個屬性就不會被序列化.
3. transient底層的實作原理是什麼?
java的serialization提供了一種存儲對象狀态的機制.将對象的狀态資料存儲到磁盤,等需要的時候将其取出來.而某些業務場景對于一些特殊的屬性不希望在網絡上傳輸,
此時transient關鍵字就起到了決定性的作用,他可以将被其修飾的對象屬性的生命周期限定在記憶體中,也就是說最終不會被寫入到記憶體.
下面有一則用例,可以快速了解關于序列化的相關内容:
package cn.api.serialize;
import java.io.*;
/**
* Serialize Api 序列化API
* Java序列化是指将java對象轉化為位元組序列的過程. 而Java反序列化是指将位元組序列恢複為java對象的過程.進而達到網絡傳輸,本地存儲的效果.
*
* transient關鍵字的應用
* 序列化的兩種方式:
* 1. Serializable
* 2. Externalizable
* Serializable和Externalizable的差別?
* Externalizable實作自Serializable.
* 使用Externalizable序列化需要實作writeExternal()和readExternal().
* 說明: 使用Externalizable實作序列化需要手動提供序列化對象的無參構造器.
* 使用Externalizable序列化不需要産生序列化ID(serialVersionUID),而通過Serializable方式實作序列化時需要初始化序列化ID(serialVersionUID).
* 相對于Serializable,使用Externalizable實作序列化其占用的記憶體要比Serializable要小,速度也要比Serializable要快.
* Serializable使用兩種方式實作序列化[
* 1. 對非transient以及非static的屬性進行序列化.
* 2. 實作writeExternal()和readExternal()進行指定屬性的序列化.
* ] 說明: Serializable不需要提供序列化對象無參構造器的原因是,Serializable使用反射機制完成内容回複.是以沒有一定要添加序列化對象的無參構造器的限制.
* 項目中為了快速響應一般都是用Serializable來完成資料對象的序列化.有些類可以使用Externalizable接口,如: [
* 完全控制序列的流程和邏輯.
* 需要大量的使用序列化和反序列化操作,此時你比較關心資源和性能.(此時也可以通過第三方序列化反序列化工具來實作. 如:protobuf(Google),thrift(Facebook),AvroGeneric...)
* ]
*/
public class SerializeApi {
/**
* Obj User
*/
static class User implements Serializable{
private final long serialVersionID = -628948656629515L;
private String name;
private transient int age;
public long getSerialVersionID() {
return serialVersionID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
/**
* Obj SerializableApiTest
* @Explain transient修飾的非靜态屬性不會被序列化(靜态屬性在公共的方法區,是以靜态變量用不用transient修飾都不會被序列化)
*/
static class SerializableApiTest {
private static void serializeUser() throws Exception {
User user = new User();
user.setName("Mir's Liu");
user.setAge(10003);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D://template"));
objectOutputStream.writeObject(user);
objectOutputStream.close();
System.out.println("transient attribute is age: " + user.getAge());
}
private static void deSerializeUser() throws Exception {
File file = new File("D://template");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User user = (User)objectInputStream.readObject();
System.out.println("revert transient attribute is age: " + user.getAge());
}
public static void main(String[] args) throws Exception{
serializeUser();
deSerializeUser();
}
}
/**
* Obj User1
* @Exceplain 使用Externalizable實作序列化後,需要實作writeExternal()和readExternal()對不需要序列化的屬性要手動設定(設定後即使transient修飾也是一樣).
*/
static class User1 implements Externalizable {
/** 實作了指定參數序列化後,加不加transient都會被序列化 */
private transient String name;
private Integer age;
/** 虛歲(Virtual year) */
private Integer virtualYear;
public User1() {}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getVirtualYear() {
return virtualYear;
}
public void setVirtualYear(Integer virtualYear) {
this.virtualYear = virtualYear;
}
/**
* 手動實作指定參數的序列化
* @param out
* @throws IOException
*/
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(name);
out.writeObject(age);
out.writeObject(virtualYear);
}
/**
* 手動實作指定參數的反序列化
* @param in
* @throws IOException
* @throws ClassNotFoundException
*/
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = (String) in.readObject();
age = (Integer) in.readObject();
virtualYear = (Integer) in.readObject();
}
@Override
public String toString() {
return "User1{" +
"name='" + name + '\'' +
", age=" + age +
", virtualYear=" + virtualYear +
'}';
}
}
/**
* Obj ExternalizeAdiTest
*/
static class ExternalizeAdiTest {
private static void externalizeUser() throws Exception {
User1 user = new User1();
user.setName("Mir's Li");
user.setAge(22);
user.setVirtualYear(23);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D://template"));
objectOutputStream.writeObject(user);
objectOutputStream.close();
System.out.println("transient attribute is name: " + user.toString());
}
private static void deExternalizeUser() throws Exception {
File file = new File("D://template");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User1 user = (User1)objectInputStream.readObject();
System.out.println("revert transient attribute is name: " + user.toString());
}
public static void main(String[] args) throws Exception{
externalizeUser();
deExternalizeUser();
}
}
/**
* Obj User2
*/
static class User2 implements Serializable {
private static transient String name;
private int age;
public static String getName() {
return name;
}
public static void setName(String name) {
User2.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User2{" +
"age=" + age +
'}';
}
}
static class StaticSerializableApiTest {
private static void serializableUser2(int age) throws Exception {
User2 user2 = new User2();
user2.setName("Mir's Li");
user2.setAge(age);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D://template"));
objectOutputStream.writeObject(user2);
objectOutputStream.close();
System.out.println("User2: (after) " + user2.toString());
}
private static void deSerializableUser2() throws Exception {
File file = new File("D://template");
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
User2 user2 = (User2)objectInputStream.readObject();
System.out.println("User2: (end) " + user2.toString());
}
public static void main(String[] args) throws Exception{
serializableUser2(12);
deSerializableUser2();
serializableUser2(122);
deSerializableUser2();
}
}
}