Java transient 关键字

问:transient 关键字能实现什么?

答:当对象被序列化时(写入字节序列到目标文件)时,transient 阻止实例中那些用此关键字声明的变量持久化;当对象被反序列化时(从源文件读取字节序列进行重构),这样的实例变量值不会被持久化和恢复。例如,当反序列化对象 —— 数据流(例如,文件)可能不存在时,原因是你的对象中存在类型为 java.io.InputStream 的变量,序列化时这些变量引用的输入流无法被打开。

问:如何使用 transient?

答:包含实例变量声明中的 transient 修饰符。下面代码提供了小的演示。

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class ClassLib implements Serializable {
    private transient InputStream is;

    private int majorVer;
    private int minorVer;

    ClassLib(InputStream is) throws IOException {
        System.out.println("ClassLib(InputStream) called");
        this.is = is;
        DataInputStream dis;
        if (is instanceof DataInputStream)
            dis = (DataInputStream) is;
        else
            dis = new DataInputStream(is);
        if (dis.readInt() != 0xcafebabe)
            throw new IOException("not a .class file");
        minorVer = dis.readShort();
        majorVer = dis.readShort();
    }

    int getMajorVer() {
        return majorVer;
    }

    int getMinorVer() {
        return minorVer;
    }

    void showIS() {
        System.out.println(is);
    }
}

public class TransDemo {
    public static void main(String[] args) throws IOException {
        if (args.length != 1) {
            System.err.println("usage: java TransDemo classfile");
            return;
        }
        ClassLib cl = new ClassLib(new FileInputStream(args[0]));
        System.out.printf("Minor version number: %d%n", cl.getMinorVer());
        System.out.printf("Major version number: %d%n", cl.getMajorVer());
        cl.showIS();

        try (FileOutputStream fos = new FileOutputStream("x.ser");
                ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(cl);
        }

        cl = null;

        try (FileInputStream fis = new FileInputStream("x.ser");
                ObjectInputStream ois = new ObjectInputStream(fis)) {
            System.out.println();
            cl = (ClassLib) ois.readObject();
            System.out.printf("Minor version number: %d%n", cl.getMinorVer());
            System.out.printf("Major version number: %d%n", cl.getMajorVer());
            cl.showIS();
        } catch (ClassNotFoundException cnfe) {
            System.err.println(cnfe.getMessage());
        }
    }
}

上面代码中声明 ClassLib 和 TransDemo 类。ClassLib 是一个读取 Java 类文件的库,并且实现了 java.io.Serializable 接口,从而这些实例能被序列化和反序列化。TransDemo 是一个用来序列化和反序列化 ClassLib 实例的应用类。

ClassLib 声明它的实例变量为 transient,原因是它可以毫无意义的序列化一个输入流(像上面讲述的那样)。事实上,如果此变量不是 transient 的话,当反序列化 x.ser 的内容时,则会抛出 java.io.NotSerializableException,原因是 InputStream 没有实现 Serializable 接口。

编译运行上面代码你或许会看到类似下面的输出:

ClassLib(InputStream) called
Minor version number: 0
Major version number: 51
java.io.FileInputStream@79f1e0e0

Minor version number: 0
Major version number: 51
null

以上输出表明:当对象被重构时,没有构造方法调用。此外,is 假定默认为 null,相比较,当 ClassLib 对象序列化时,majorVer 和 minorVer 是有值的。

问:类中的成员变量中可以使用 transient 吗?

答:问题答案请看如下代码段。

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Foo implements Serializable
{
   public static int w = 1;
   public static transient int x = 2;
   public int y = 3;
   public transient int z = 4;
}

public class TransDemo
{
   public static void main(String[] args) throws IOException
   {
      Foo foo = new Foo();
      System.out.printf("w: %d%n", Foo.w);
      System.out.printf("x: %d%n", Foo.x);
      System.out.printf("y: %d%n", foo.y);
      System.out.printf("z: %d%n", foo.z);
      try (FileOutputStream fos = new FileOutputStream("x.ser");
           ObjectOutputStream oos = new ObjectOutputStream(fos))
      {
         oos.writeObject(foo);
      }

      foo = null;

      try (FileInputStream fis = new FileInputStream("x.ser");
           ObjectInputStream ois = new ObjectInputStream(fis))
      {
         System.out.println();
         foo = (Foo) ois.readObject();
         System.out.printf("w: %d%n", Foo.w);
         System.out.printf("x: %d%n", Foo.x);
         System.out.printf("y: %d%n", foo.y);
         System.out.printf("z: %d%n", foo.z);
      }
      catch (ClassNotFoundException cnfe)
      {
         System.err.println(cnfe.getMessage());
      }
   }
}

编译运行上面代码可以看到如下输出:

w: 1
x: 2
y: 3
z: 4

w: 1
x: 2
y: 3
z: 0

这个输出告诉我们,实例变量 y 是被序列化的,z 却没有,它被标记 transient。但是,当 Foo 被序列化时,它并没有告诉我们,是否变量 w 和 x 被序列化和反序列化,是否只是以普通类初始化方式初始。因为 z 是 transient,所以不能序列化。此外,即使它们标记 transien,w 和 x 不能被序列化,原因是它们类变量不能序列化。

翻译: ImportNew.com - xbing
原文链接: http://www.javaworld.com/article/2074911/java-se/transience.html
译文链接: http://www.importnew.com/12611.html

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,238评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,430评论 3 415
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,134评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,893评论 1 309
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,653评论 6 408
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,136评论 1 323
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,212评论 3 441
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,372评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,888评论 1 334
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,738评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,939评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,482评论 5 359
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,179评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,588评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,829评论 1 283
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,610评论 3 391
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,916评论 2 372

推荐阅读更多精彩内容