为什么 Java 有瞬态字段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/910374/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:59:27  来源:igfitidea点击:

Why does Java have transient fields?

javafieldtransient

提问by Animesh

Why does Java have transientfields?

为什么 Java 有瞬态字段?

采纳答案by coobird

The transientkeyword in Java is used to indicate that a field should not be part of the serialization (which means saved, liketo a file) process.

transientJava 中的关键字用于指示字段不应成为序列化(这意味着已保存,例如保存到文件)过程的一部分。

From the Java Language Specification, Java SE 7 Edition, Section 8.3.1.3. transientFields:

来自Java 语言规范,Java SE 7 版第 8.3.1.3 节。transient领域

Variables may be marked transientto indicate that they are not part of the persistent state of an object.

可以标记变量transient以指示它们不是对象持久状态的一部分。

For example, you may have fields that are derived from other fields, and should only be done so programmatically, rather than having the state be persisted via serialization.

例如,您可能有从其他字段派生的字段,并且只能以编程方式完成,而不是通过序列化来持久化状态。

Here's a GalleryImageclass which contains an image and a thumbnail derived from the image:

这是一个GalleryImage包含图像和从图像派生的缩略图的类:

class GalleryImage implements Serializable
{
    private Image image;
    private transient Image thumbnailImage;

    private void generateThumbnail()
    {
        // Generate thumbnail.
    }

    private void readObject(ObjectInputStream inputStream)
            throws IOException, ClassNotFoundException
    {
        inputStream.defaultReadObject();
        generateThumbnail();
    }    
}

In this example, the thumbnailImageis a thumbnail image that is generated by invoking the generateThumbnailmethod.

在本示例中,thumbnailImage是通过调用该generateThumbnail方法生成的缩略图图像。

The thumbnailImagefield is marked as transient, so only the original imageis serialized rather than persisting both the original image and the thumbnail image. This means that less storage would be needed to save the serialized object. (Of course, this may or may not be desirable depending on the requirements of the system -- this is just an example.)

thumbnailImage字段被标记为transient,因此只有image原始图像被序列化,而不是同时保留原始图像和缩略图图像。这意味着保存序列化对象所需的存储空间更少。(当然,这可能是也可能不是理想的,这取决于系统的要求——这只是一个例子。)

At the time of deserialization, the readObjectmethod is called to perform any operations necessary to restore the state of the object back to the state at which the serialization occurred. Here, the thumbnail needs to be generated, so the readObjectmethod is overridden so that the thumbnail will be generated by calling the generateThumbnailmethod.

在反序列化时,readObject调用该方法以执行将对象的状态恢复到发生序列化时的状态所需的任何操作。这里需要生成缩略图,所以readObject重写该方法,以便通过调用该generateThumbnail方法来生成缩略图。

For additional information, the Discover the secrets of the Java Serialization APIarticle (which was originally available on the Sun Developer Network) has a section which discusses the use of and presents a scenario where the transientkeyword is used to prevent serialization of certain fields.

有关其他信息,Discover the secrets of the Java Serialization API文章(最初可在 Sun Developer Network 上找到)有一个部分讨论了使用transient关键字来防止某些字段序列化的情况,并提供了一个场景。

回答by Brian Agnew

To allow you to define variables that you don't want to serialize.

允许您定义不想序列化的变量。

In an object you may have information that you don't want to serialize/persist (perhaps a reference to a parent factory object), or perhaps it doesn't make sense to serialize. Marking these as 'transient' means the serialization mechanism will ignore these fields.

在一个对象中,您可能有不想序列化/持久化的信息(可能是对父工厂对象的引用),或者序列化可能没有意义。将这些标记为“transient”意味着序列化机制将忽略这些字段。

回答by Silfverstrom

Because not all variables are of a serializable nature

因为并非所有变量都具有可序列化的性质

回答by Adrian Grigore

A transientvariable is a variable that may not be serialized.

transient变量是可以不被序列化的变量。

One example of when this might be useful that comes to mind is, variables that make only sense in the context of a specific object instance and which become invalid once you have serialized and deserialized the object. In that case it is useful to have those variables become nullinstead so that you can re-initialize them with useful data when needed.

想到这可能有用的一个例子是,变量只在特定对象实例的上下文中有意义,并且一旦您序列化和反序列化对象就会变得无效。在这种情况下,让这些变量变成是有用的,null这样您就可以在需要时用有用的数据重新初始化它们。

回答by setzamora

It's needed when you don't want to share some sensitive data that go with serialization.

当您不想共享一些与序列化相关的敏感数据时需要它。

回答by DragonFax

Serialization systems other than the native java one can also use this modifier. Hibernate, for instance, will not persist fields marked with either @Transientor the transientmodifier. Terracotta as well respects this modifier.

除了本机 java 之外的序列化系统也可以使用此修饰符。例如,Hibernate 不会保留标有@Transient瞬态修饰符的字段。兵马俑也尊重这个修饰符。

I believe the figurative meaning of the modifier is "this field is for in-memory use only. don't persist or move it outside of this particular VM in any way. Its non-portable". i.e. you can't rely on its value in another VM memory space. Much like volatilemeans you can't rely on certain memory and thread semantics.

我相信修饰符的比喻意义是“该字段仅用于内存中。不要以任何方式将其持久化或移动到此特定 VM 之外。它不可移植”。即你不能依赖它在另一个 VM 内存空间中的值。很像volatile意味着您不能依赖某些内存和线程语义。

回答by Andrei Ciobanu

transientis used to indicate that a class field doesn't need to be serialized. Probably the best example is a Threadfield. There's usually no reason to serialize a Thread, as its state is very 'flow specific'.

transient用于表示类字段不需要序列化。最好的例子可能是一个Thread字段。通常没有理由序列化 a Thread,因为它的状态非常“特定于流”。

回答by Rahul Saxena

Before understanding the transientkeyword, one has to understand the concept of serialization. If the reader knows about serialization, please skip the first point.

在了解transient关键字之前,必须先了解序列化的概念。如果读者知道序列化,请跳过第一点。

What is serialization?

什么是序列化?

Serialization is the process of making the object's state persistent. That means the state of the object is converted into a stream of bytes to be used for persisting (e.g. storing bytes in a file) or transferring (e.g. sending bytes across a network). In the same way, we can use the deserialization to bring back the object's state from bytes. This is one of the important concepts in Java programming because serialization is mostly used in networking programming. The objects that need to be transmitted through the network have to be converted into bytes. For that purpose, every class or interface must implement the Serializableinterface. It is a marker interface without any methods.

序列化是使对象的状态持久化的过程。这意味着对象的状态被转换成字节流以用于持久化(例如在文件中存储字节)或传输(例如通过网络发送字节)。同样,我们可以使用反序列化从字节中恢复对象的状态。这是 Java 编程中的重要概念之一,因为序列化主要用于网络编程。需要通过网络传输的对象必须转换为字节。为此,每个类或接口都必须实现该Serializable接口。它是一个没有任何方法的标记接口。

Now what is the transientkeyword and its purpose?

现在什么是transient关键字及其目的?

By default, all of object's variables get converted into a persistent state. In some cases, you may want to avoid persisting some variables because you don't have the need to persist those variables. So you can declare those variables as transient. If the variable is declared as transient, then it will not be persisted. That is the main purpose of the transientkeyword.

默认情况下,对象的所有变量都会转换为持久状态。在某些情况下,您可能希望避免保留某些变量,因为您不需要保留这些变量。因此,您可以将这些变量声明为transient. 如果变量声明为transient,则它不会被持久化。这就是transient关键字的主要用途。

I want to explain the above two points with the following example:

我想用下面的例子来解释以上两点:

package javabeat.samples;

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

class NameStore implements Serializable{
    private String firstName;
    private transient String middleName;
    private String lastName;

    public NameStore (String fName, String mName, String lName){
        this.firstName = fName;
        this.middleName = mName;
        this.lastName = lName;
    }

    public String toString(){
        StringBuffer sb = new StringBuffer(40);
        sb.append("First Name : ");
        sb.append(this.firstName);
        sb.append("Middle Name : ");
        sb.append(this.middleName);
        sb.append("Last Name : ");
        sb.append(this.lastName);
        return sb.toString();
    }
}

public class TransientExample{
    public static void main(String args[]) throws Exception {
        NameStore nameStore = new NameStore("Steve", "Middle","Jobs");
        ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream("nameStore"));
        // writing to object
        o.writeObject(nameStore);
        o.close();

        // reading from object
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("nameStore"));
        NameStore nameStore1 = (NameStore)in.readObject();
        System.out.println(nameStore1);
    }
}

And the output will be the following:

输出如下:

First Name : Steve
Middle Name : null
Last Name : Jobs

Middle Nameis declared as transient, so it will not be stored in the persistent storage.

Middle Name声明为transient,因此不会存储在持久存储中。

Source

来源

回答by Shreyos Adikari

My small contribution :

我的小贡献:

What is a transient field?
Basically, any field modified with the transientkeyword is a transient field.

Why are transient fields needed in Java?
The transientkeyword gives you some control over the serialization process and allows you to exclude some object properties from this process. The serialization process is used to persist Java objects, mostly so that their states can be preserved while they are transferred or inactive. Sometimes, it makes sense not to serialize certain attributes of an object.

Which fields should you mark transient?
Now we know the purpose of the transientkeyword and transient fields, it's important to know which fields to mark transient. Static fields aren't serialized either, so the corresponding keyword would also do the trick. But this might ruin your class design; this is where the transientkeyword comes to the rescue. I try not to allow fields whose values can be derived from others to be serialized, so I mark them transient. If you have a field called interestwhose value can be calculated from other fields (principal, rate& time), there is no need to serialize it.

Another good example is with article word counts. If you are saving an entire article, there's really no need to save the word count, because it can be computed when article gets "deserialized." Or think about loggers; Loggerinstances almost never need to be serialized, so they can be made transient.

什么是瞬态场?
基本上,任何用transient关键字修改的字段都是瞬态字段。

为什么 Java 中需要瞬态字段?
transient关键字使您可以对序列化过程进行一些控制,并允许您从该过程中排除某些对象属性。序列化过程用于持久化 Java 对象,主要是为了在它们传输或不活动时保留它们的状态。有时,不序列化对象的某些属性是有意义的。

您应该将哪些字段标记为瞬态?
现在我们知道了transient关键字和瞬态字段,重要的是要知道哪些字段标记为瞬态。静态字段也不会序列化,因此相应的关键字也可以解决问题。但这可能会破坏您的类设计;这就是transient关键字派上用场的地方。我尽量不允许其值可以从其他人派生的字段被序列化,因此我将它们标记为瞬态。如果您有一个名为interest的字段,其值可以从其他字段 ( principal, rate& time)计算出来,则无需对其进行序列化。

另一个很好的例子是文章字数统计。如果您要保存整篇文章,则实际上没有必要保存字数,因为可以在文章“反序列化”时进行计算。或者想想记录器;Logger实例几乎从不需要序列化,因此它们可以是瞬态的。

回答by Mateen

As per google transient meaning == lasting only for a short time; impermanent.

根据谷歌瞬态含义 == 仅持续很短的时间;暂时的。

Now if you want to make anything transient in java use transient keyword.

现在,如果您想在 java 中使任何东西变得瞬态,请使用瞬态关键字。

Q: where to use transient?

问:在哪里使用瞬态?

A:Generally in java we can save data to files by acquiring them in variables and writing those variables to files, this process is known as Serialization. Now if we want to avoid variable data to be written to file, we would make that variable as transient.

A:一般在java中我们可以通过在变量中获取数据并将这些变量写入文件来将数据保存到文件中,这个过程被称为序列化。现在,如果我们想避免将变量数据写入文件,我们可以将该变量设为瞬态。

transient int result=10;

Note:transient variables cannot be local.

注意:瞬态变量不能是局部的。