transient关键字简述
将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。 关于序列化: Java序列化提供两种方式。
- 一种是实现Serializable接口
- 另一种是实现Exteranlizable接口。 需要重写writeExternal和readExternal方法,它的效率比Serializable高一些,并且可以决定哪些属性需要序列化(即使是transient修饰的),但是对大量对象,或者重复对象,则效率低。
代码:
public class TransientTest {
public static void main(String[] args) {
Person person = new Person("张三", 22);
System.out.println("序列化前:");
System.out.println(person);
System.out.println(person.getOCCUPATION());
System.out.println(person.getTEST());
ByteOutputStream bos = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
bos = new ByteOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(person);
oos.flush();
person.setOCCUPATION("厨师");
person.setTEST("测试");
ois = new ObjectInputStream(bos.newInputStream());
Person deserialization = (Person) ois.readObject();
System.out.println("反序列化后");
System.out.println(deserialization);
System.out.println(deserialization.getOCCUPATION());
System.out.println(deserialization.getTEST());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
class Person implements Serializable {
private String name;
private transient int age;
public static String OCCUPATION = "程序猿";
public static transient String TEST = "test";
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
public String getOCCUPATION() {
return OCCUPATION;
}
public void setOCCUPATION(String OCCUPATION) {
Person.OCCUPATION = OCCUPATION;
}
public String getTEST() {
return TEST;
}
public void setTEST(String TEST) {
Person.TEST = TEST;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
运行结果: 序列化前: Person{name=‘张三’, age=22} 程序猿 test 反序列化后 Person{name=‘张三’, age=0} 厨师 测试 简析: 可以看到加了transient关键字的int类型的age并没有被序列化成功,而是默认的值0。
深入transien关键字
transient的底层实现原理
java的serialization提供了一个非常棒的存储对象状态的机制,serialization就是把对象的状态存储到硬盘上 去,等需要的时候就可以再把它读出来使用。有些时候像银行卡号这些字段是不希望在网络上传输的,transient的作用就是把这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化,意思是transient修饰的age字段,他的生命周期仅仅在内存中,不会被写到磁盘中。
被transient关键字修饰过得变量真的不能被序列化嘛?
是的
静态变量能被序列化吗?被transient关键字修饰之后呢?
静态变量是不会被序列化的,即使没有transient关键字修饰,因为静态成员变量实际上是属于类,而不是对象。
静态变量在全局区,本来流里面就没有写入静态变量,我打印静态变量当然会去全局区查找,而我们的序列化是写到磁盘上的,所以JVM查找这个静态变量的值,是从全局区查找的,而不是磁盘上。上面在改变static修饰的变量是在序列化后,但打印反序列化的对象的被static修饰的变量也同样改变了;这是因为在改变static修饰的变量时,是被写到了全局区,其实就是方法区,只不过被所有的线程共享的一块空间。 因此: 静态变量不管是不是transient关键字修饰,都不会被序列化
|