今天在看JDK的一些源码的时候,发现有一个关键字transient自己没怎么玩过。所以这里写此博客来整理下这个关键字的用法。
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
翻找资料的时候,有一篇不错的博客,原文地址:http://www.cnblogs.com/dolphin0520/p/3933551.html。感谢作者的无私分享。
首先我们先写一段代码来序列化和反序列化一个Java对象:
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @创建作者: LinkinPark
* @创建时间: 2016年1月6日
*
* @功能描述:序列化和反序列化一个对象
*/
public class Test7
{
private static final String filePath = "/Users/LinkinPark/Desktop/linkin.txt";
public static void main(String[] args)
{
User user = new User().setUserName("LinkinPark").setPassWord("Binger1214");
// 序列化一个对象
try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath)))
{
os.writeObject(user);
System.out.println(user.toString());
}
catch (IOException e)
{
e.printStackTrace();
}
// 反序列化一个对象
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath)))
{
User userByRead = (User) in.readObject();
System.out.println(userByRead.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class User implements Serializable
{
private String userName;// 用户姓名
private String passWord;// 密码
public String getUserName()
{
return userName;
}
public User setUserName(String userName)
{
this.userName = userName;
return this;
}
public String getPassWord()
{
return passWord;
}
public User setPassWord(String passWord)
{
this.passWord = passWord;
return this;
}
@Override
public String toString()
{
return "User [userName=" + userName + ", passWord=" + passWord + "]";
}
}
OK,现在我们使用这个transient关键字来修饰User对象的密码属性,代码如下:
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* @创建作者: LinkinPark
* @创建时间: 2016年1月6日
*
* @功能描述:transient关键字使用
*/
public class Test7
{
private static final String filePath = "/Users/LinkinPark/Desktop/linkin.txt";
public static void main(String[] args)
{
User user = new User().setUserName("LinkinPark").setPassWord("Binger1214");
// 序列化一个对象
try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(filePath)))
{
os.writeObject(user);
System.out.println(user.toString());
}
catch (IOException e)
{
e.printStackTrace();
}
// 反序列化一个对象
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filePath)))
{
User userByRead = (User) in.readObject();
System.out.println(userByRead.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class User implements Serializable
{
private String userName;// 用户姓名
private transient String passWord;// 密码
public String getUserName()
{
return userName;
}
public User setUserName(String userName)
{
this.userName = userName;
return this;
}
public String getPassWord()
{
return passWord;
}
public User setPassWord(String passWord)
{
this.passWord = passWord;
return this;
}
@Override
public String toString()
{
return "User [userName=" + userName + ", passWord=" + passWord + "]";
}
}
对比2次控制台的输出,我们发现java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
再明显一点我们打开2次序列化后的linkin.txt文件,发现第2次明显的没有将密码这个字段序列化到文件中。通过上面的实践,这里来总结下transient关键字的用法:
1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。关于这点就不做多的解释了,类变量属于类的属性,存在于JVM内存中的,不能被序列化。