首页 文章

为什么Java有瞬态字段?

提问于
浏览
1260

为什么Java有 transient 字段?

12 回答

  • 1

    transient 变量是可能未序列化的变量 .

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

  • 378

    根据谷歌暂时意义==只持续很短的时间;暂时的 .

    现在如果想在java中做任何瞬态使用transient关键字 .

    问:在哪里使用瞬态?

    答:通常在java中,我们可以通过在变量中获取数据并将这些变量写入文件来将数据保存到文件中,此过程称为序列化 . 现在,如果我们想要避免将可变数据写入文件,我们会将该变量设置为瞬态 .

    transient int result = 10;

    Note: 瞬态变量不能是本地的 .

  • 6

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

    什么是序列化?

    序列化是从字节开始使对象's state persistent. That means the state of the object is converted into a stream of bytes and stored in a file. In the same way, we can use the deserialization to bring back the object'状态的过程 . 这是Java编程中的重要概念之一,因为序列化主要用于网络编程 . 需要通过网络传输的对象必须转换为字节 . 为此,每个类或接口都必须实现Serializable接口 . 它是没有任何方法的标记界面 .

    现在什么是transient关键字及其用途?

    默认情况下,所有对象's variables get converted into a persistent state. In some cases, you may want to avoid persisting some variables because you don' t都需要保留这些变量 . 因此,您可以将这些变量声明为 transient . 如果变量声明为 transient ,那么它将不会被持久化 . 这是 transient 关键字的主要目的 .

    我想通过以下示例解释上述两点:

    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);
        }
    }
    

    输出将如下:

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

    中间名声明为 transient ,因此它不会存储在持久存储中 .

    Source

  • 1479

    当您不想共享序列化的敏感数据时,需要它 .

  • 80

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

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

  • 13

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

  • 1

    transient 用于指示不需要序列化类字段 . 可能最好的例子是 Thread 字段 . 通常没有理由序列化 Thread ,因为它的状态非常'flow specific' .

  • 9

    我的小贡献:

    What is a transient field?
    基本上,使用 transient 关键字修改的任何字段都是瞬态字段 .

    Why are transient fields needed in Java?
    transient 关键字使您可以控制序列化过程,并允许您从此过程中排除某些对象属性 . 序列化过程用于持久化Java对象,主要是为了在传输或非活动状态时保留它们的状态 . 有时,不序列化对象的某些属性是有意义的 .

    Which fields should you mark transient?
    现在我们知道 transient 关键字和瞬态字段的用途,它也可以序列化,所以相应的关键字也可以实现 . 但这可能会破坏你的 class 设计;这是 transient 关键字拯救的地方 . 我尽量不允许其值可以从其他人派生的字段被序列化,所以我将它们标记为瞬态 . 如果您有一个名为 interest 的字段,其值可以从其他字段( principalratetime )计算,则无需序列化它 .

    另一个很好的例子是文章字数 . 如果你要保存整篇文章,那么实际上不需要保存单词计数,因为它可以在文章得到_135895时计算出来或者考虑 Logger ; Logger 实例几乎从不需要序列化,因此它们可以变为瞬态 .

  • 31

    在回答这个问题之前,我必须向你解释 SERIALIZATION ,因为如果你理解科学计算机中序列化的含义,你可以很容易地理解这个关键词 .

    Serialization 当通过网络传输对象/保存在物理介质(文件,...)上时,该对象必须为"serialized" . 序列化转换字节状态对象系列 . 这些字节在网络上发送/保存,并从这些字节重新创建对象 .

    public class Foo implements Serializable 
    {
     private String attr1;
     private String attr2;
     ...
    }
    

    现在,如果你不想 TRANSFERT / SAVED 这个对象的字段 SO ,你可以使用 keyword transient

    private transient attr2;
    

    Example

  • 21

    Java中的 transient 关键字用于指示字段不应该是序列化(这意味着保存,比如文件)过程的一部分 .

    来自Java Language Specification, Java SE 7 EditionSection 8.3.1.3. transient Fields

    变量可以标记为瞬态,表示它们不是对象持久状态的一部分 .

    例如,您可能具有从其他字段派生的字段,并且只应以编程方式执行,而不是通过序列化保持状态 .

    这是 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();
        }    
    }
    

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

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

    在反序列化时,调用readObject方法以执行将对象状态恢复到序列化发生状态所需的任何操作 . 这里需要生成缩略图,因此会覆盖 readObject 方法,以便通过调用 generateThumbnail 方法生成缩略图 .

    有关其他信息,Discover the secrets of the Java Serialization API文章(最初在Sun Developer Network上提供)中有一节讨论了使用 transient 关键字以防止某些字段序列化的情况,并提供了一个方案 .

  • 10

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

    我相信修饰语的比喻意思是"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" . 即你不能在另一个VM内存空间中依赖它的值 . 很像 volatile 意味着你不能依赖某些内存和线程语义 .

  • 3

    简单地说,瞬态java关键字保护来自Serialize的字段作为非瞬态字段计数器部分 .

    在这段代码片段中,我们的抽象类BaseJob实现了Serializable接口,我们从BaseJob扩展,但我们不需要序列化远程和本地数据源;仅序列化organizationName和isSynced字段 .

    public abstract class BaseJob implements Serializable{
       public void ShouldRetryRun(){}
    }
    
    public class SyncOrganizationJob extends BaseJob {
    
       public String organizationName;
       public Boolean isSynced
    
       @Inject transient RemoteDataSource remoteDataSource;
       @Inject transient LocalDaoSource localDataSource;
    
       public SyncOrganizationJob(String organizationName) {
         super(new 
             Params(BACKGROUND).groupBy(GROUP).requireNetwork().persist());
    
          this.organizationName = organizationName;
          this.isSynced=isSynced;
    
       }
    }
    

相关问题