transient的用途及使用方法

版权声明:未经允许不得转载,转载前请标明转载地址:http://blog.csdn.net/ShyTan https://blog.csdn.net/ShyTan/article/details/82429115

transient的用途及使用方法

<--预热:序列化的理解-->

  • 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。
  • 然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。
  • 总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

1,用途

  我们知道,当一个对象实现了Serilizable接口,这个对象就可以被序列化,我们不关心其内在的原理,只需要了解这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。而在开发过程中,我们可能要求:当对象被序列化时(写入字节序列到目标文件)时,有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。 
 所以,transient的用途在于:阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象——数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为java.io.InputStream的变量,序列化时这些变量引用的输入流无法被打开。

2,使用方法

序列化的时候,将不需要序列化的属性前添加关键字transient即可。 
示例:

<span style="color:#000000"><code><span style="color:#000088">package</span> newDay.day13;

<span style="color:#000088">import</span> java.io.FileInputStream;
<span style="color:#000088">import</span> java.io.FileOutputStream;
<span style="color:#000088">import</span> java.io.ObjectInputStream;
<span style="color:#000088">import</span> java.io.ObjectOutputStream;
<span style="color:#000088">import</span> java.io.Serializable;

class UserInfo implements Serializable {  
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> <span style="color:#000088">long</span> serialVersionUID = <span style="color:#006666">996890129747019948</span>L;  
    <span style="color:#000088">private</span> String name;  
    <span style="color:#000088">private</span> <span style="color:#000088">transient</span> String psw;  

    <span style="color:#000088">public</span> <span style="color:#009900">UserInfo</span>(String name, String psw) {  
        <span style="color:#000088">this</span>.name = name;  
        <span style="color:#000088">this</span>.psw = psw;  
    }  

    <span style="color:#000088">public</span> String <span style="color:#009900">toString</span>() {  
        <span style="color:#000088">return</span> <span style="color:#009900">"name="</span> + name + <span style="color:#009900">", psw="</span> + psw;  
    }  
}  
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">TestTransient</span> {
    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">main</span>(String[] args) {  
        UserInfo userInfo = <span style="color:#000088">new</span> UserInfo(<span style="color:#009900">"张三"</span>, <span style="color:#009900">"123456"</span>);  
        System.out.println(userInfo);  
        <span style="color:#000088">try</span> {  
            <span style="color:#880000">// 序列化,被设置为transient的属性没有被序列化  </span>
            ObjectOutputStream o = <span style="color:#000088">new</span> ObjectOutputStream(<span style="color:#000088">new</span> FileOutputStream(<span style="color:#009900">"UserInfo.txt"</span>));  
            o.writeObject(userInfo);  
            o.close();  
        } <span style="color:#000088">catch</span> (Exception e) {  
            <span style="color:#880000">// TODO: handle exception  </span>
            e.printStackTrace();  
        }  
        <span style="color:#000088">try</span> {  
            <span style="color:#880000">// 重新读取内容  </span>
            ObjectInputStream in = <span style="color:#000088">new</span> ObjectInputStream(<span style="color:#000088">new</span> FileInputStream(<span style="color:#009900">"UserInfo.txt"</span>));  
            UserInfo readUserInfo = (UserInfo) in.readObject();  
            <span style="color:#880000">//读取后psw的内容为null  </span>
            System.out.println(readUserInfo.toString());  
        } <span style="color:#000088">catch</span> (Exception e) {  
            <span style="color:#880000">// TODO: handle exception  </span>
            e.printStackTrace();  
        }  
    }  
}</code></span>

运行结果:

<span style="color:#000000"><code>name=张三, psw=<span style="color:#006666">123456</span>
name=张三, psw=null</code></span>

  密码字段为null,说明被标记为transient的属性在对象被序列化的时候不会被保存。

使用小结:

  1,一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。 
  2,transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。 
  3,被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。 
  对于第三点,加上static之后,依然能把姓名输出。这是因为:反序列化后类中static型变量name的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的。下例可说明,其值时JVM中得到的而不是反序列化得到的:

<span style="color:#000000"><code><span style="color:#000088">package</span> newDay.day13;

<span style="color:#000088">import</span> java.io.FileInputStream;
<span style="color:#000088">import</span> java.io.FileOutputStream;
<span style="color:#000088">import</span> java.io.ObjectInputStream;
<span style="color:#000088">import</span> java.io.ObjectOutputStream;
<span style="color:#000088">import</span> java.io.Serializable;

class UserInfo implements Serializable {  
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> <span style="color:#000088">long</span> serialVersionUID = <span style="color:#006666">996890129747019948</span>L;  
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> String name;  
    <span style="color:#000088">private</span> <span style="color:#000088">transient</span> String psw;  

    <span style="color:#000088">public</span> <span style="color:#009900">UserInfo</span>(String name, String psw) {  
        <span style="color:#000088">this</span>.name = name;  
        <span style="color:#000088">this</span>.psw = psw;  
    }  

    <span style="color:#000088">public</span> <span style="color:#000088">static</span> String <span style="color:#009900">getName</span>() {
        <span style="color:#000088">return</span> name;
    }

    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">setName</span>(String name) {
        UserInfo.name = name;
    }

    <span style="color:#000088">public</span> String <span style="color:#009900">getPsw</span>() {
        <span style="color:#000088">return</span> psw;
    }

    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setPsw</span>(String psw) {
        <span style="color:#000088">this</span>.psw = psw;
    }

    <span style="color:#000088">public</span> String <span style="color:#009900">toString</span>() {  
        <span style="color:#000088">return</span> <span style="color:#009900">"name="</span> + name + <span style="color:#009900">", psw="</span> + psw;  
    }  
}  
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">TestTransient</span> {
    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">main</span>(String[] args) {  
        UserInfo userInfo = <span style="color:#000088">new</span> UserInfo(<span style="color:#009900">"张三"</span>, <span style="color:#009900">"123456"</span>); 
        System.out.println(userInfo);  
        <span style="color:#000088">try</span> {  
            <span style="color:#880000">// 序列化,被设置为transient的属性没有被序列化  </span>
            ObjectOutputStream o = <span style="color:#000088">new</span> ObjectOutputStream(<span style="color:#000088">new</span> FileOutputStream(<span style="color:#009900">"UserInfo.txt"</span>));  
            o.writeObject(userInfo);  
            o.close();  
        } <span style="color:#000088">catch</span> (Exception e) {  
            <span style="color:#880000">// TODO: handle exception  </span>
            e.printStackTrace();  
        }  
        <span style="color:#000088">try</span> {  
            <span style="color:#880000">//在反序列化之前改变name的值</span>
            userInfo.setName(<span style="color:#009900">"hello"</span>);
            <span style="color:#880000">// 重新读取内容  </span>
            ObjectInputStream in = <span style="color:#000088">new</span> ObjectInputStream(<span style="color:#000088">new</span> FileInputStream(<span style="color:#009900">"UserInfo.txt"</span>));  
            UserInfo readUserInfo = (UserInfo) in.readObject();  
            <span style="color:#880000">//读取后psw的内容为null  </span>
            System.out.println(readUserInfo.toString());  
        } <span style="color:#000088">catch</span> (Exception e) {  
            <span style="color:#880000">// TODO: handle exception  </span>
            e.printStackTrace();  
        }  
    }  
}</code></span>

运行结果:

<span style="color:#000000"><code>name=张三, psw=<span style="color:#006666">123456</span>
name=hello, psw=null</code></span>

这说明反序列化后类中static型变量name的值为当前JVM中对应static变量的值,为修改后hello,而不是序列化时的值“张三”

猜你喜欢

转载自blog.csdn.net/ShyTan/article/details/82429115
今日推荐