栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

transient关键字解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

transient关键字解析

transient关键字的定义

定义:transient只能用来修饰成员变量(field),被transient修饰的成员变量不参与序列化过程。
简析:Java中的对象如果想要在网络上传输或者存储在磁盘时,就必须要序列化。Java中序列化的本质是Java对象转换为字节序列。但是在序列化的过程中,可以允许被序列对象中的某个成员变量不参与序列化,即该对象完成序列化之后,被transient修饰的成员变量会在字节序列中消失。

小明的昵称希望被人看到,但是真名不希望被人看到。

package com.ygl.demo3;

import java.io.Serializable;

public class XiaoMing implements Serializable {
    private static final long serialVersionUID = 1271321732347324L;
    private String nickName;
    private transient String realName;

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public XiaoMing(String nickName, String realName) {
        this.nickName = nickName;
        this.realName = realName;
    }

    @Override
    public String toString() {
        return "XiaoMing{" +
                "nickName='" + nickName + ''' +
                ", realName='" + realName + ''' +
                '}';
    }
}

package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing {
    public static void main(String[] args) throws IOException {
        XiaoMing xiaoMing = new XiaoMing("ming", "鸿铭");
        System.out.println("序列化前:"+xiaoMing.toString());
        ObjectOutputStream oo = null;
        ObjectInputStream oi = null;
        try {
            oo = new ObjectOutputStream(new FileOutputStream(new File("./xiaoming.txt")));
            oo.writeObject(xiaoMing);
            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
            XiaoMing x = (XiaoMing) oi.readObject();
            System.out.println("序列化后:"+x.toString());
        }catch (IOException | ClassNotFoundException e){
            System.out.println(e.getStackTrace());
        }finally {
            oi.close();
            oo.close();
        }
    }
}

结果

序列化前:XiaoMing{nickName='ming', realName='鸿铭'}
序列化后:XiaoMing{nickName='ming', realName='null'}
静态成员变量不加transient关键字也不能被序列化

在Java中,静态成员变量是不能被序列化的,不管有没有transient关键字。

The readObject method is responsible for reading from the stream and 
restoring the classes fields. It may call in.defaultReadObject to
invoke the default mechanism for restoring the object's non-static 
and non-transient fields. The defaultReadObject method uses 
information in the stream to assign the fields of the object saved in
the stream with the correspondingly named fields in the current 
object. This handles the case when the class has evolved to add new
fields. The method does not need to concern itself with the state 
belonging to its superclasses or subclasses. State is saved by 
writing the individual fields to the ObjectOutputStream using the 
writeObject method or by using the methods for primitive data types
supported by DataOutput.
package com.ygl.demo3;

import java.io.Serializable;

public class XiaoMing implements Serializable {
    private static final long serialVersionUID = 1271321732347324L;
    private String nickName;
    private transient String realName;
    private static String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        XiaoMing.address = address;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public XiaoMing(String nickName, String realName) {
        this.nickName = nickName;
        this.realName = realName;
    }

    @Override
    public String toString() {
        return "XiaoMing{" +
                "nickName='" + nickName + ''' +
                ", realName='" + realName + ''' +
                '}';
    }

}

package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing {
    public static void main(String[] args) throws IOException {
        XiaoMing xiaoMing = new XiaoMing("ming", "鸿铭");
        xiaoMing.setAddress("西府大街22号");
        System.out.println("序列化前:"+xiaoMing.toString()+xiaoMing.getAddress());
        ObjectOutputStream oo = null;
        ObjectInputStream oi = null;
        try {
            oo = new ObjectOutputStream(new FileOutputStream(new File("./xiaoming.txt")));
            oo.writeObject(xiaoMing);
            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
            XiaoMing x = (XiaoMing) oi.readObject();
            System.out.println("序列化后:"+x.toString()+x.getAddress());
        }catch (IOException | ClassNotFoundException e){
            System.out.println(e.getStackTrace());
        }finally {
            oi.close();
            oo.close();
        }
    }
}

结果发现加了static关键字的address成员变量可以反序列化,这是为什么呢?
因为测试都在同一个机器(而且是同一个进程),因为这个jvm已经把address加载进来了,所以获取的是加载好的address,如果是传到另一台机器或者关掉程序重新写个程序读入xiaoming.txt,此时因为别的机器或新的进程是重新加载i的,所以address信息就是初始时的信息null

序列化前:XiaoMing{nickName='ming', realName='鸿铭'}西府大街22号
序列化后:XiaoMing{nickName='ming', realName='null'}西府大街22号
package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing {
    public static void main(String[] args) throws IOException {
        XiaoMing xiaoMing = new XiaoMing("ming", "鸿铭");
        xiaoMing.setAddress("西府大街22号");
        System.out.println("序列化前:"+xiaoMing.toString()+xiaoMing.getAddress());
        ObjectOutputStream oo = null;
        //ObjectInputStream oi = null;
        try {
            oo = new ObjectOutputStream(new FileOutputStream(new File("./xiaoming.txt")));
            oo.writeObject(xiaoMing);
//            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
//            XiaoMing x = (XiaoMing) oi.readObject();
//            System.out.println("序列化后:"+x.toString()+x.getAddress());
        }catch (IOException e){
            System.out.println(e.getStackTrace());
        }finally {
            //oi.close();
            oo.close();
        }
    }
}

package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing2 {
    public static void main(String[] args) throws IOException {
        ObjectInputStream oi = null;
        try {
            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
            XiaoMing x = (XiaoMing) oi.readObject();
            System.out.println("序列化后:"+x.toString()+x.getAddress());
        }catch (IOException | ClassNotFoundException e){
            System.out.println(e.getStackTrace());
        }finally {
            oi.close();
        }
    }
}

序列化后:XiaoMing{nickName='ming', realName='null'}null
使用Externalizable自定义序列化

Externalizable这个接口也是实现序列化的,但是和Serializable有不同。首先,Externalizable是继承Serializable的,其次Externalizable是需要程序员自己指定成员变量实现序列化的。

也就是说,使用Externalizable接口,程序员需要实现writeExternal以及readExternal这两个方法,来自己实现序列化和反序列化。实现的过程中,需要自己指定需要序列化的成员变量,此时,static和transient关键词都是不生效的,因为你重写了序列化中的方法。

package com.ygl.demo3;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class XiaoMing2 implements Externalizable {
    private static final long serialVersionUID = 1271321732347324L;
    private String nickName;
    private transient String realName;
    private static String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        XiaoMing2.address = address;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public XiaoMing2(String nickName, String realName) {
        this.nickName = nickName;
        this.realName = realName;
    }

    public XiaoMing2() {
    }

    @Override
    public String toString() {
        return "XiaoMing{" +
                "nickName='" + nickName + ''' +
                ", realName='" + realName + ''' +
                '}';
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(realName);
        out.writeUTF(nickName);
        out.writeUTF(XiaoMing2.address);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        realName = in.readUTF();
        nickName = in.readUTF();
        XiaoMing2.address = in.readUTF();
    }
}

package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing {
    public static void main(String[] args) throws IOException {
        XiaoMing2 xiaoMing = new XiaoMing2("ming", "鸿铭");
        xiaoMing.setAddress("西府大街22号");
        System.out.println("序列化前:"+xiaoMing.toString()+xiaoMing.getAddress());
        ObjectOutputStream oo = null;
        //ObjectInputStream oi = null;
        try {
            oo = new ObjectOutputStream(new FileOutputStream(new File("./xiaoming.txt")));
            oo.writeObject(xiaoMing);
//            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
//            XiaoMing x = (XiaoMing) oi.readObject();
//            System.out.println("序列化后:"+x.toString()+x.getAddress());
        }catch (IOException e){
            System.out.println(e.getStackTrace());
        }finally {
            //oi.close();
            oo.close();
        }
    }
}

package com.ygl.demo3;

import java.io.*;

public class TestXiaoMing2 {
    public static void main(String[] args) throws IOException {
        ObjectInputStream oi = null;
        try {
            oi = new ObjectInputStream(new FileInputStream(new File("./xiaoming.txt")));
            XiaoMing2 x = (XiaoMing2)oi.readObject();
            System.out.println("序列化后:"+x.toString()+x.getAddress());
        }catch (IOException | ClassNotFoundException e){
            System.out.println(e.getStackTrace());
        }finally {
            oi.close();
        }
    }
}

序列化后:XiaoMing{nickName='ming', realName='鸿铭'}西府大街22号
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821175.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号