Java'nın neden geçici alanları var?


Yanıtlar:


1673

transientJava anahtar bir alan (Kaydedilen demektir serileştirme parçası olmaması gerektiğini belirtmek için kullanılır gibi sürecine bir dosya için).

Gönderen Java Dil Şartname, Java SE 7 Sürümü , Bölüm 8.3.1.3. transientAlanlar :

Değişkenler transient, bir nesnenin kalıcı durumunun bir parçası olmadığını belirtmek için işaretlenebilir .

Örneğin, diğer alanlardan türetilmiş alanlarınız olabilir ve durumun serileştirme yoluyla kalıcı hale getirilmesi yerine yalnızca programlı olarak yapılması gerekir.

İşte GalleryImagebir görüntü ve görüntüden türetilmiş bir küçük resim içeren bir sınıf:

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

Bu örnekte, yöntem thumbnailImageçağrılarak oluşturulan küçük resim görüntüsüdür generateThumbnail.

thumbnailImageSaha işaretlenir transientböylece sadece orijinal, imageorijinal görüntü ve küçük resim hem devam eden ziyade seri hale. Bu, serileştirilmiş nesneyi kaydetmek için daha az depolama alanı gerektiği anlamına gelir. (Elbette, sistemin gereksinimlerine bağlı olarak bu istenebilir veya istenmeyebilir - bu sadece bir örnektir.)

Serileştirme readObjectsırasında, nesnenin durumunu serileştirmenin gerçekleştiği duruma geri döndürmek için gerekli işlemleri gerçekleştirmek için yöntem çağrılır. Burada, küçük resmin oluşturulması gerekir, bu readObjectnedenle küçük resim generateThumbnailyöntem çağrılarak oluşturulacak şekilde yöntem geçersiz kılınır .

Ek bilgi için, Java Serialization API'sının (başlangıçta Sun Developer Network'te bulunan) sırlarını keşfedin makalesinin transient, belirli alanların serileştirilmesini önlemek için anahtar kelimenin kullanıldığını tartışan ve kullandığı bir senaryo vardır .


221
Ama neden bir ek açıklama değil bir anahtar kelime @DoNotSerialize?
Elazar Leibovich

333
Sanırım, bu Java'da ek açıklamaların olmadığı bir zamana aittir.
Peter Wippermann

46
Ben serileştirilebilir Java iç olduğunu garip buluyorum. Kullanıcıların okuma ve yazma yöntemlerini geçersiz kılmalarını gerektiren bir arabirim veya soyut sınıf olarak uygulanabilir.
caleb

7
@MJafar: readObject genellikle serileştirme mekanizmalarına zincirlenir ve otomatik olarak çağrılır. Ayrıca, birçok durumda geçersiz kılmanıza gerek yoktur - varsayılan uygulama hile yapar.
Mike Adler

13
@caleb muhtemelen, ikili formatlarla uğraşmak, imzalanmamış tam sayıların olmaması nedeniyle Java'da inanılmaz derecede acı vericidir.
rightfold

435

transientAnahtar kelimeyi anlamadan önce , serileştirme kavramını anlamak gerekir. Okuyucu serileştirmeyi biliyorsa, lütfen ilk noktayı atlayın.

Serileştirme nedir?

Serileştirme, nesnenin durumunu kalıcı hale getirme işlemidir. Bu, nesnenin durumunun kalıcı (örn. Bir dosyada bayt depolanması) veya aktarılması (örneğin bir ağ üzerinden bayt gönderilmesi) için kullanılacak bir bayt akışına dönüştürüldüğü anlamına gelir. Aynı şekilde, nesnenin durumunu baytlardan geri getirmek için serileştirmeyi kullanabiliriz. Bu, Java programlamasındaki önemli kavramlardan biridir çünkü serileştirme çoğunlukla ağ programlamasında kullanılır. Ağ üzerinden iletilmesi gereken nesnelerin bayta dönüştürülmesi gerekir. Bu amaçla, her sınıf veya arabirim arabirimi uygulamalıdır Serializable. Herhangi bir yöntemi olmayan bir marker arayüzüdür.

Şimdi transientanahtar kelime ve amacı nedir?

Varsayılan olarak, nesnenin tüm değişkenleri kalıcı duruma dönüştürülür. Bazı durumlarda, bazı değişkenleri devam ettirmekten kaçınmak isteyebilirsiniz, çünkü bu değişkenleri devam ettirmeniz gerekmez. Böylece bu değişkenleri olarak bildirebilirsiniz transient. Değişken olarak bildirilirse transient, kalıcı olmayacaktır. transientAnahtar kelimenin ana amacı budur .

Yukarıdaki iki noktayı aşağıdaki örnekle açıklamak istiyorum:

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

Ve çıktı aşağıdaki gibi olacaktır:

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

İkinci Ad olarak bildirilir transient, bu nedenle kalıcı depolama alanında depolanmaz.

Kaynak


26
Bu örnek bu koddan alınmıştır, buradan okuyabilirsiniz: javabeat.net/2009/02/what-is-transient-keyword-in-java
Krishna

11
Bu bölüm bana garip ve kafa karıştırıcı geliyor: "Bu, nesnenin durumunun bir bayt akışına dönüştürüldüğü ve bir dosyada saklandığı anlamına gelir ". Bana öyle geliyor ki çoğu zaman serileştirme bir dosyaya yazmayı içermiyor (bu durumda: takip eden ağ örnekleri)
Garcia Hurtado

5
Örnek kötüdür, çünkü ikinci ad açıkça geçici bir özellik değildir .
Raphael

1
@ Raphael Benim için örnek faydalı ve en azından kavramı açıklıyor. Farkındaysanız daha iyi bir örnek verir misiniz?
Chaklader Asfak Arefe

@Yoda Araç kullanmak için NameFormatterkullanılmış bir referansımız olabilir toString(). Veya yapılandırma, görüntüleme veya iş mantığı ile ilgili başka herhangi bir şey ... verilerin aksine.
Raphael

84

Serileştirmek istemediğiniz değişkenleri tanımlamanıza izin vermek için.

Bir nesnede serileştirmek / kalıcı hale getirmek istemediğiniz bilgilere (belki de bir üst fabrika nesnesine bir referans) sahip olabilirsiniz veya serileştirmek mantıklı değildir. Bunları 'geçici' olarak işaretlemek, serileştirme mekanizmasının bu alanları yok sayacağı anlamına gelir.


36

Benim küçük katkım:

Geçici alan nedir?
Temel olarak, transientanahtar kelimeyle değiştirilen herhangi bir alan geçici bir alandır.

Java'da geçici alanlara neden ihtiyaç duyulur? Anahtar kelime size seri süreci üzerinde bir miktar kontrol sağlar ve bu süreçten bazı nesne özelliklerini çıkarılmasına izin verir. Serileştirme işlemi Java nesnelerini devam ettirmek için kullanılır, böylece durumları aktarılırken veya devre dışı bırakılırken korunabilir. Bazen, bir nesnenin belirli niteliklerini serileştirmemek mantıklıdır. Geçici olarak hangi alanları işaretlemelisiniz? Şimdi amacını biliyoruz
transient


transientanahtar kelime ve geçici alanlar için, geçici olarak hangi alanların işaretleneceğini bilmek önemlidir. Statik alanlar da serileştirilmediğinden, karşılık gelen anahtar kelime de işe yarayacaktır. Ama bu sınıf tasarımınızı mahvedebilir; transientanahtar kelimenin kurtarmaya geldiği yer burasıdır . Değerleri başkalarından türetilebilecek alanların serileştirilmesine izin vermemeye çalışıyorum, bu yüzden onları geçici olarak işaretliyorum. interestDeğeri diğer alanlardan ( principal, rate& time) hesaplanabilecek bir alanınız varsa, bunu serileştirmeye gerek yoktur.

Başka bir iyi örnek makale kelime sayımlarıdır. Bir makalenin tamamını kaydediyorsanız, kelime sayısını kaydetmeye gerek yoktur, çünkü makale "serileştirilmiş" hale geldiğinde hesaplanabilir. Veya kaydedicileri düşünün;Logger Örneklerin neredeyse hiçbir zaman serileştirilmesine gerek yoktur, bu nedenle geçici hale getirilebilirler.


63
'Basit cümleniz' sadece bir totolojidir. Hiçbir şeyi açıklamıyor. Onsuz daha iyi olurdun.
user207421

1
Bu alanın olması gerektiği güzel bir açıklamatransient
Chaklader Asfak Arefe

1
ilgi alanı ve kelime sayıları geçici alanlara iyi örneklerdir.
Tarun

1
Başka bir iyi kullanım örneği: Nesnenizde soket gibi bileşenler varsa ve serileştirmek istiyorsanız sokete ne olur? Eğer devam ederse, seriyi kaldırdıktan sonra soketin elinde ne olacaktı? Bu soket nesnesini şu şekilde yapmak mantıklıdırtransient
Mohammed Siddiq

28

Bir transientdeğişken getirilemez olabilecek bir değişkendir.

Bunun akla gelen yararlı olabileceğinin bir örneği, belirli bir nesne örneği bağlamında yalnızca anlamlı olan ve nesneyi serileştirip serileştirdiğinizde geçersiz hale gelen değişkenlerdir. Bu durumda, bu değişkenlerin nullyerine dönüştürülmesi yararlı olur, böylece gerektiğinde bunları yararlı verilerle yeniden başlatabilirsiniz.


evet, bir sınıfın "password veya crediCardPin" alan üyeleri gibi bir şey.
Mateen

17

transientsınıf alanının serileştirilmesi gerekmediğini belirtmek için kullanılır. Muhtemelen en iyi örnek bir Threadalandır. Durumu Threadçok 'akışa spesifik' olduğundan, a'yı serileştirmek için genellikle bir neden yoktur .


Yanılıyorsam beni düzeltin, ancak Thread yine de atlanacak şekilde serileştirilemez mi?
TFennis

3
@TFennis: Bir seri hale getirilebilir sınıf ise Abaşvurular bir değil seri hale getirilebilir sınıf B(gibi Threadsizin örnekte), sonra Asıra ya referansını işaretlemek gerekir transientmakul bir şey yapmak amacıyla XOR varsayılan seri hale getirme işlemini geçersiz kılmalıdır Bsadece seri hale getirilebilir alt sınıfları varsayalım XOR Baslında başvurulan (bu nedenle gerçek alt sınıf "kötü" üst Böğelerine dikkat etmelidir) XOR, serileştirmenin başarısız olacağını kabul eder. Sadece bir durumda (geçici olarak işaretlenir) Botomatik ve sessizce atlanır.
AH

3
@TFennis Hayır, bir istisnaya neden olacaktır.
user207421

1
@AH: Neden XOR? Bu şeylerin herhangi bir kombinasyonu yaptı kod işe yarayacağını düşünürdüm ve bazı kombinasyonlar yararlı olabilir (örneğin, yalnızca serileştirilebilir alt sınıfları başvurulan ve hatta tam tersi olsa bile, varsayılan serileştirme sürecini geçersiz kılmak yararlı olabilir).
supercat

15

Yerel java dışındaki serileştirme sistemleri de bu değiştiriciyi kullanabilir. Örneğin, hazırda bekletme modu @Transient veya geçici değiştirici ile işaretli alanları sürdürmez . Terracotta da bu değiştiriciye saygı duyar.

Değiştiricinin mecazi anlamının "bu alan sadece bellek içi kullanım içindir. Devam etmeyin veya herhangi bir şekilde bu VM'nin dışına taşımayın. Taşınabilir değil". başka bir VM bellek alanındaki değerine güvenemezsiniz. Çok gibi uçucu araçlarla belirli bellek ve iplik semantik güvenemez.


14
Ben düşünüyorum transientşu an için tasarlanmış sanki bir anahtar kelimeyi olmaz. Muhtemelen bir ek açıklama kullanırlardı.
Joachim Sauer


7

Bu soruya cevap vermeden önce, size SERIALİZASYONU açıklamalıyım , çünkü bilim bilgisayarında serileştirmenin ne anlama geldiğini anlarsanız, bu anahtar kelimeyi kolayca anlayabilirsiniz.

Serileştirme Bir nesne ağ üzerinden aktarıldığında / fiziksel ortama (dosya, ...) kaydedildiğinde, nesnenin "serileştirilmesi" gerekir. Serileştirme bayt durumu nesne serisini dönüştürür. Bu baytlar ağa gönderilir / kaydedilir ve nesne bu baytlardan yeniden oluşturulur.
Misal

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

SİZE DEĞİL yapmak İSTİYORUM Şimdi TRANSFERT / KAYDEDİLDİ Bu nesnenin alanını SO kullanabileceğiniz anahtar kelime transient

private transient attr2;

Misal


6

Serileştirme ile ilgili bazı hassas verileri paylaşmak istemediğinizde gereklidir.


7
Bir alanı serileştirmek istemeyebileceğiniz hassas veriler dışında kullanım durumları vardır. Örneğin, muhtemelen hiçbir zaman Thread(örneğin @AH'a kredi) serileştirmek istemezsiniz , bu durumda geçici olarak işaretlersiniz. Bununla birlikte, bir iş parçacığı kendi başına hassas veriler değildir, sadece serileştirmek için mantıklı bir anlam ifade etmez (ve serileştirilemez).
glen3b

1
@ glen3b Bu durum bu cevap tarafından hariç tutulmadı. Söz konusu posterde işler dururken kesinlikle gereklidir.
user207421

3

Google kısa süreli anlamı == sadece kısa bir süre süren; süreksiz.

Java'da geçici bir şey yapmak istiyorsanız şimdi geçici anahtar kelime kullanın.

S: Geçici nerede kullanılır?

C: Genellikle java'da verileri değişkenlerde elde ederek ve bu değişkenleri dosyalara yazarak dosyalara kaydedebiliriz, bu işleme Serileştirme adı verilir. Şimdi değişken verilerin dosyaya yazılmasını önlemek istiyorsak, bu değişkeni geçici olarak yaparız.

transient int result=10;

Not: geçici değişkenler yerel olamaz.


0

Basitçe söylemek gerekirse, geçici java anahtar sözcüğü, geçici olmayan alan sayaç parçaları olarak alanları Serialize'den korur.

Bu kod snippet'inde soyut sınıf BaseJob Serializable arabirimini uygular, BaseJob'dan genişleriz, ancak uzak ve yerel veri kaynaklarını serileştirmemize gerek yoktur; yalnızca organizationName ve isSynced alanlarını serileştirin.

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;

   }
}

0

Geçici anahtar kelime için basitleştirilmiş örnek kod.

import java.io.*;

class NameStore implements Serializable {
    private String firstName, lastName;
    private transient String fullName;

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

    private void buildFullName() {
        // assume building fullName is compuational/memory intensive!
        this.fullName = this.firstName + " " + this.lastName;
    }

    public String toString(){
        return "First Name : " + this.firstName
            + "\nLast Name : " + this.lastName
            + "\nFull Name : " + this.fullName;
    }

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

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

        ObjectInputStream in = new ObjectInputStream(new FileInputStream("ns"));
        NameStore ns = (NameStore)in.readObject();
        System.out.println(ns);
    }
}

0

Geçici değiştirici ile bildirilen bir alan, serileştirilmiş sürece katılmayacaktır. Bir nesne serileştirildiğinde (herhangi bir durumda kaydedildiğinde) geçici alanlarının değerleri seri gösterimlerinde yoksayılırken, geçici alanlar dışındaki alan serileştirme işleminde yer alır. Geçici anahtar kelimenin temel amacı budur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.