java中的transient关键字

2021-02-24  本文已影响0人  大风过岗

1、介绍

在本文中,我们先讲解一下transient关键字,之后我们会通过几个案例来看下具体的用法。

2、transient的用法

在理解transient之前,我们要先弄清楚java中的序列化。序列化指的是把一个java对象转化成一个字节流。反序列化则相反,它是把一个字节流转化为一个java对象。当我们把某个变量标记为transient时,之后该变量就不会被序列化了。因此,序列化进程transient变量的原始值会被忽略,并且之会保存其数据类型所对应的默认值。

在以下这些场景中,transient关键字是非常有用的:

. 我们可以使用它处理衍生字段

. 我们可以用它来处理那些和对象状态无关的字段

. 我们可以用它来处理那些不能序列化的引用字段

3、案例

我们通过一个例子来看。我们先创建一个Book类,然后我们对这个Book类的对象执行序列化。

/**
 * @Author: chihaojie
 * @Date: 2021/2/24 10:45
 * @Version 1.0
 * @Note
 */
public class Book  implements Serializable {

    private static final long serialVersionUID = -2936687026040726549L;

    private String bookName;
    private transient String description;
    private transient int    copies;


    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getCopies() {
        return copies;
    }

    public void setCopies(int copies) {
        this.copies = copies;
    }
}

这里,我们把description和copies字段标记为transient。创建完这个类之后,我们再创建一个该类的对象。

Book book = new Book();

       book.setBookName("Java Reference");
       book.setDescription("will not be saved");
       book.setCopies(25);


现在,我们把这个对象序列化进一个文件中:


public static void serialize(Book book) throws Exception {
    FileOutputStream file = new FileOutputStream(fileName);
    ObjectOutputStream out = new ObjectOutputStream(file);
    out.writeObject(book);
    out.close();
    file.close();
}

接着我们再从文件中反序列化此对象:

public static Book deserialize() throws Exception {
    FileInputStream file = new FileInputStream(fileName);
    ObjectInputStream in = new ObjectInputStream(file);
    Book book = (Book) in.readObject();
    in.close();
    file.close();
    return book;
}

完整的程序示例为:


public class TransientMain {


    public static void main(String[] args)throws Exception {
        Book book = new Book();

        book.setBookName("Java Reference");
        book.setDescription("will not be saved");
        book.setCopies(25);

        serialize(book);
        Book deserializeBook = deserialize();

        System.out.println(deserializeBook.getBookName());
        System.out.println(deserializeBook.getDescription());
        System.out.println(deserializeBook.getCopies());
    }

    public static void serialize(Book book) throws Exception{

        FileOutputStream    file  =  new FileOutputStream("book.txt");
        ObjectOutputStream  out   =  new ObjectOutputStream(file);
        out.writeObject(book);
        out.close();
        file.close();
    }

    public static Book deserialize() throws Exception{

        FileInputStream     file    = new FileInputStream("book.txt");
        ObjectInputStream   in      = new ObjectInputStream(file);
        Book                book    = (Book) in.readObject();
        in.close();
        file.close();
        return book;
    }
}

控制台的输出如下:

控制台输出

我们可以看到,bookName字段被序列化了,而copies字段的值为0,description字段的值为null-这都是他们各自所属数据类型的默认值-而不是它们原本的字段值。

4、transient和final组合使用

我们再来看一个特殊的场景,我们把transient和final组合在一起使用。要做到这点,首先,我们在Book类中新增一个final transient字段,接着,我们再创建一个空的Book对象。

public class Book  implements Serializable {

    private static final long serialVersionUID = -2936687026040726549L;

    private String bookName;
    private transient String description;
    private transient int    copies;


    private final transient String  bookCategory    = "Fiction";


    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public int getCopies() {
        return copies;
    }

    public void setCopies(int copies) {
        this.copies = copies;
    }

    public String getBookCategory() {
        return bookCategory;
    }
}

测试程序:

public class TransientMain {


    public static void main(String[] args)throws Exception {
        Book book = new Book();

        book.setBookName("Java Reference");
        book.setDescription("will not be saved");
        book.setCopies(25);

        serialize(book);
        Book deserializeBook = deserialize();

        System.out.println(deserializeBook.getBookName());
        System.out.println(deserializeBook.getDescription());
        System.out.println(deserializeBook.getCopies());
        System.out.println(deserializeBook.getBookCategory());
    }

    public static void serialize(Book book) throws Exception{

        FileOutputStream    file  =  new FileOutputStream("book.txt");
        ObjectOutputStream  out   =  new ObjectOutputStream(file);
        out.writeObject(book);
        out.close();
        file.close();
    }

    public static Book deserialize() throws Exception{

        FileInputStream     file    = new FileInputStream("book.txt");
        ObjectInputStream   in      = new ObjectInputStream(file);
        Book                book    = (Book) in.readObject();
        in.close();
        file.close();
        return book;
    }
}


运行程序,观察控制台的输出情况:

控制台输出情况

5、总结

在本文中,我们介绍了transient关键字的用法,以及它在序列化和反序列化中的作用。同时,我们也看到了它和final组合使用时效果。

6、参考文献

  1. stackoverflow-why-does-java-have-transient-fields

  2. jls-13.4.11

  3. baedung-java-transient-keyword

  4. 序列化与反序列化

  5. Discover the secrets of the Java Serialization API

上一篇下一篇

猜你喜欢

热点阅读