背景: 抽空整理一下.特此纪要!
问题:
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();
}
}
}