Java 中的 transient 关键字
最后更新:2024年5月11日
1. 简介
在本文中,我们首先理解 transient 关键字,然后通过示例了解它在不同数据类型上的行为方式。
2. transient 的使用
在转向 transient 之前,让我们先理解序列化,因为它是在序列化上下文中使用的。
序列化是将对象转换为字节流的过程,而反序列化则是它的逆过程.
当我们把任何变量标记为 transient 时,该变量将不会被序列化。由于 transient 字段不存在于对象的序列化形式中,反序列化过程在从序列化形式创建对象时,将对这些字段使用默认值(空或 0)。
transient 关键字在以下几种情况下很有用
- 我们可以将其用于派生字段
- 它对不代表对象状态的字段很有用
- 我们将其用于任何不可序列化的引用
- 当我们想要存储敏感信息并且不想通过网络发送它时
3. 示例
为了实际演示,让我们首先创建一个 Book 类,它的对象我们想要序列化
public class Book implements Serializable {
private static final long serialVersionUID = -2936687026040726549L;
private String bookName;
private transient String description;
private transient int copies;
// getters and setters
}
在这里,我们将 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;
}
最后,我们将验证 book 对象的值
assertEquals("Java Reference", book.getBookName());
assertNull(book.getDescription());
assertEquals(0, book.getCopies());
在这里我们可以看到 bookName 已被正确持久化。另一方面,copies 字段的值为 0 ,description 为 null – 它们的各自数据类型的默认值 – 而不是原始值。
4. 与 final 的行为
现在,让我们看看我们将 transient 与 final 关键字一起使用的案例。为此,我们首先在我们的 Book 类中添加一个 final transient 元素,然后创建一个空的 Book 对象
public class Book implements Serializable {
// existing fields
private final transient String bookCategory = "Fiction";
// getters and setters
}
Book book = new Book();
final 修饰符在具有字面量初始化时没有区别。当将 String 类型的变量声明为 final 和 transient 时,其值在编译时确定并存储在类的常量池中。由于它是 final,因此在初始化后无法更改其值。因此,其值将从类中获取,而不是空。
有关 String 池的更多信息,请访问我们的文章 Java String Pool 指南。
assertEquals("Fiction", book.getBookCategory());
4.1. 使用 new 运算符 与 final String 的行为
现在让我们看一个将 transient 与 final 关键字一起使用的案例。为此,我们将在我们的 Book 类中使用 new 运算符创建一个具有 final 和 transient 的 String 变量,然后创建一个空的 Book 对象
public class Book implements Serializable {
// existing fields
private final transient String bookCategoryNewOperator = new String("Fiction with new Operator");
// getters and setters
}
Book book = new Book();
在这种情况下,使用 new 运算符 初始化 String 将在堆内存中创建对象,并且我们在反序列化时此对象的默认值为 null。
assertNull(book.getBookCategoryNewOperator());
5. 结论
在本文中,我们了解了 transient 关键字的用法及其在序列化和反序列化中的行为,其中包含一些不明显的示例,例如带有 transient 的 String。
支持本文的代码可在 GitHub 上获取。 一旦你以 Baeldung Pro 会员 身份登录,就开始学习并在项目上进行编码。















