Mengapa Java memiliki bidang sementara?

Jawaban:

1673

Kata transientkunci dalam Java digunakan untuk menunjukkan bahwa suatu bidang tidak boleh menjadi bagian dari proses serialisasi (yang berarti disimpan, seperti ke file).

Dari Spesifikasi Bahasa Jawa , Edisi Java SE 7 , Bagian 8.3.1.3. transientBidang :

Variabel dapat ditandai transientuntuk menunjukkan bahwa mereka bukan bagian dari keadaan gigih suatu objek.

Misalnya, Anda mungkin memiliki bidang yang berasal dari bidang lain, dan seharusnya hanya dilakukan secara terprogram, alih-alih keadaan dipertahankan melalui serialisasi.

Inilah GalleryImagekelas yang berisi gambar dan gambar mini yang berasal dari gambar:

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

Dalam contoh ini, thumbnailImagegambar thumbnail yang dihasilkan dengan memanggil generateThumbnailmetode.

The thumbnailImagelapangan ditandai sebagai transient, sehingga hanya asli imageserial daripada bertahan kedua gambar asli dan gambar thumbnail. Ini berarti bahwa penyimpanan yang lebih sedikit akan diperlukan untuk menyimpan objek serial. (Tentu saja, ini mungkin atau mungkin tidak diinginkan tergantung pada persyaratan sistem - ini hanya sebuah contoh.)

Pada saat deserialisasi, readObjectmetode dipanggil untuk melakukan operasi yang diperlukan untuk mengembalikan keadaan objek kembali ke keadaan di mana serialisasi terjadi. Di sini, thumbnail perlu dibuat, sehingga readObjectmetode ditimpa sehingga thumbnail akan dihasilkan dengan memanggil generateThumbnailmetode.

Untuk informasi tambahan, temukan rahasia artikel Java Serialization API (yang semula tersedia di Sun Developer Network) memiliki bagian yang membahas penggunaan dan menyajikan skenario di mana transientkata kunci digunakan untuk mencegah serialisasi bidang-bidang tertentu.

coobird
sumber
221
Tapi mengapa itu kata kunci, dan bukan anotasi @DoNotSerialize?
Elazar Leibovich
333
Saya kira, ini milik waktu ketika tidak ada penjelasan di Jawa.
Peter Wippermann
46
Saya merasa aneh bahwa serializable adalah internal Java. Ini dapat diimplementasikan sebagai antarmuka atau kelas abstrak yang mengharuskan pengguna untuk mengganti metode baca dan tulis.
caleb
7
@ MJafar: readObject biasanya dirantai ke mekanisme deserialisasi dan dengan demikian disebut secara otomatis. Selain itu, dalam banyak kasus Anda tidak perlu mengesampingkannya - implementasi default melakukan trik.
Mike Adler
13
@caleb mungkin karena berurusan dengan format biner sendiri sangat menyakitkan di Jawa karena kurangnya bilangan bulat yang tidak ditandatangani.
sayap kanan
435

Sebelum memahami transientkata kunci, kita harus memahami konsep serialisasi. Jika pembaca tahu tentang serialisasi, lewati poin pertama.

Apa itu serialisasi?

Serialisasi adalah proses untuk membuat keadaan objek tetap. Itu berarti keadaan objek diubah menjadi aliran byte yang akan digunakan untuk bertahan (misalnya menyimpan byte dalam file) atau mentransfer (misalnya mengirim byte melalui jaringan). Dengan cara yang sama, kita dapat menggunakan deserialization untuk mengembalikan status objek dari byte. Ini adalah salah satu konsep penting dalam pemrograman Java karena serialisasi banyak digunakan dalam pemrograman jaringan. Objek-objek yang perlu ditransmisikan melalui jaringan harus dikonversi menjadi byte. Untuk tujuan itu, setiap kelas atau antarmuka harus mengimplementasikan Serializableantarmuka. Ini adalah antarmuka marker tanpa metode apa pun.

Sekarang apa transientkata kunci dan tujuannya?

Secara default, semua variabel objek bisa dikonversi menjadi status persisten. Dalam beberapa kasus, Anda mungkin ingin menghindari beberapa variabel karena Anda tidak perlu mempertahankan variabel-variabel tersebut. Jadi, Anda dapat mendeklarasikan variabel tersebut sebagai transient. Jika variabel dinyatakan sebagai transient, maka itu tidak akan bertahan. Itulah tujuan utama transientkata kunci.

Saya ingin menjelaskan dua poin di atas dengan contoh berikut:

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

Dan hasilnya adalah sebagai berikut:

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

Nama Tengah dinyatakan sebagai transient, sehingga tidak akan disimpan dalam penyimpanan persisten.

Sumber

Rahul Saxena
sumber
26
Contoh ini diambil dari kode ini, Anda dapat membacanya di sini: javabeat.net/2009/02/what-is-transient-keyword-in-java
Krishna
11
Bagian ini menurut saya aneh dan mungkin membingungkan: "Itu berarti keadaan objek diubah menjadi aliran byte dan disimpan dalam file ". Tampak bagi saya bahwa sebagian besar serialisasi waktu tidak melibatkan penulisan ke file (contohnya: contoh jaringan yang mengikuti)
Garcia Hurtado
5
Contohnya adalah yang buruk, karena nama tengah jelas bukan properti sementara.
Raphael
1
@ Raphael Bagi saya, contohnya sangat membantu dan setidaknya menjelaskan konsepnya. Apakah Anda akan memberikan contoh yang lebih baik jika Anda sadar?
Chaklader Asfak Arefe
@Yoda Kita bisa memiliki referensi NameFormatterke drive yang digunakan toString(). Atau hal lain yang terkait dengan konfigurasi, atau tampilan, atau logika bisnis, ... yang bertentangan dengan data.
Raphael
84

Untuk memungkinkan Anda menentukan variabel yang tidak ingin Anda buat bersambung.

Dalam sebuah objek Anda mungkin memiliki informasi yang tidak ingin Anda buat bersambung / bertahan (mungkin referensi ke objek pabrik induk), atau mungkin tidak masuk akal untuk membuat cerita bersambung. Menandai ini sebagai 'sementara' berarti mekanisme serialisasi akan mengabaikan bidang ini.

Brian Agnew
sumber
36

Kontribusi kecil saya:

Apa itu bidang sementara?
Pada dasarnya, bidang apa pun yang dimodifikasi dengan transientkata kunci adalah bidang sementara.

Mengapa bidang sementara dibutuhkan di Jawa?
Kata transientkunci memberi Anda kontrol atas proses serialisasi dan memungkinkan Anda mengecualikan beberapa properti objek dari proses ini. Proses serialisasi digunakan untuk bertahan objek Java, sebagian besar sehingga negara mereka dapat dipertahankan saat mereka ditransfer atau tidak aktif. Terkadang, masuk akal untuk tidak membuat serial atribut tertentu dari suatu objek.

Bidang mana yang harus Anda tandai sementara?
Sekarang kita tahu tujuan daritransientkata kunci dan bidang sementara, penting untuk mengetahui bidang mana yang menandai sementara. Bidang statis juga tidak diserialisasi, jadi kata kunci yang sesuai juga akan melakukan trik. Tetapi ini mungkin merusak desain kelas Anda; Di sinilah transientkata kunci datang untuk menyelamatkan. Saya mencoba untuk tidak membiarkan bidang yang nilainya dapat diturunkan dari orang lain untuk serial, jadi saya tandai mereka sementara. Jika Anda memiliki bidang bernama interestyang nilainya dapat dihitung dari bidang lain ( principal, rate& time), tidak perlu diserialisasi.

Contoh lain yang baik adalah dengan jumlah kata artikel. Jika Anda menyimpan seluruh artikel, benar-benar tidak perlu menyimpan jumlah kata, karena itu dapat dihitung ketika artikel menjadi "deserialized." Atau pikirkan tentang penebang;Logger contoh hampir tidak pernah perlu serial, sehingga dapat dibuat sementara.

Shreyos Adikari
sumber
63
'Kalimat sederhana' Anda hanyalah tautologi. Itu tidak menjelaskan apa-apa. Anda akan lebih baik tanpanya.
Marquis of Lorne
1
Ini adalah penjelasan yang bagus di mana ladang itu beradatransient
Chaklader Asfak Arefe
1
bidang minat dan jumlah kata adalah contoh bagus bidang sementara.
Tarun
1
Kasus penggunaan lain yang baik: Jika objek Anda memiliki komponen seperti soket dan jika Anda ingin membuat cerita bersambung maka apa yang terjadi pada soket? Jika akan bertahan, setelah Anda deserialize apa yang akan memegang soket? Masuk akal untuk membuat objek soket itu sebagaitransient
Mohammed Siddiq
28

Sebuah transientvariabel adalah variabel yang tidak dapat serial.

Salah satu contoh kapan ini mungkin berguna yang muncul dalam pikiran adalah, variabel yang hanya masuk akal dalam konteks contoh objek tertentu dan yang menjadi tidak valid setelah Anda membuat serial dan deserialized objek. Dalam hal ini berguna untuk menjadikan variabel-variabel itu sebagai nullgantinya sehingga Anda dapat menginisialisasi ulang mereka dengan data yang berguna saat dibutuhkan.

Adrian Grigore
sumber
ya, beberapa hal seperti "kata sandi atau crediCardPin" anggota suatu kelas.
Mateen
17

transientdigunakan untuk menunjukkan bahwa bidang kelas tidak perlu diserialisasi. Mungkin contoh terbaik adalah Threadbidang. Biasanya tidak ada alasan untuk membuat serial a Thread, karena kondisinya sangat 'spesifik aliran'.

Andrei Ciobanu
sumber
Koreksi saya jika saya salah, tetapi Thread tidak bisa serial sehingga akan dilewati?
TFennis
3
@TFennis: Jika sebuah kelas serial Amereferensikan kelas tidak serialerial B(seperti Threadpada contoh Anda), maka Aharus menandai referensi sebagai transientXOR harus mengabaikan proses serialisasi default untuk melakukan sesuatu yang masuk akal dengan BXOR mengasumsikan bahwa hanya subclass serializable Byang benar-benar dirujuk. (jadi subclass yang sebenarnya harus mengurus induk "buruk" mereka B) XOR menerima bahwa serialisasi akan gagal. Hanya dalam satu kasus (ditandai sebagai sementara) Bsecara otomatis dan diam-diam dilewati.
AH
3
@TFennis Tidak, itu akan menyebabkan pengecualian.
Marquis of Lorne
1
@AH: Kenapa XOR? Saya akan berpikir kode yang melakukan kombinasi hal-hal itu akan bekerja, dan beberapa kombinasi mungkin berguna (misalnya mengganti proses serialisasi default mungkin berguna bahkan jika hanya subclass serializable B yang dirujuk, dan sebaliknya).
supercat
15

Sistem serialisasi selain yang asli Jawa juga dapat menggunakan pengubah ini. Hibernate, misalnya, tidak akan bertahan bidang ditandai dengan @Transient atau pengubah sementara . Terracotta juga menghormati pengubah ini.

Saya percaya arti kiasan dari pengubah adalah "bidang ini hanya untuk penggunaan dalam memori. Jangan bertahan atau memindahkannya di luar VM khusus ini dengan cara apa pun. Ini tidak portabel". yaitu Anda tidak dapat mengandalkan nilainya di ruang memori VM lain. Mirip volatile, Anda tidak bisa mengandalkan memori dan semantik utas tertentu.

DragonFax
sumber
14
Saya pikir itu transienttidak akan menjadi kata kunci jika dirancang pada saat ini. Mereka mungkin menggunakan anotasi.
Joachim Sauer
9

Karena tidak semua variabel bersifat serializable

Silfverstrom
sumber
42
Harap berikan informasi lebih lanjut ketika Anda memberikan jawaban.
Danny Gloudemans
7

Sebelum saya menjawab pertanyaan ini, saya harus menjelaskan kepada Anda SERIALISASI , karena jika Anda mengerti apa artinya serialisasi dalam ilmu komputer Anda dapat dengan mudah memahami kata kunci ini.

Serialisasi Ketika suatu objek ditransfer melalui jaringan / disimpan pada media fisik (file, ...), objek tersebut harus "serial". Serialisasi mengubah seri objek status byte. Bytes ini dikirim pada jaringan / disimpan dan objek dibuat kembali dari byte ini.
Contoh

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

Sekarang JIKA ANDA INGIN lakukan TIDAK TRANSFERT / DISELAMATKAN bidang objek ini SO , Anda dapat menggunakan kata kunci transient

private transient attr2;

Contoh

BERGUIGA Mohamed Amine
sumber
6

Ini diperlukan ketika Anda tidak ingin berbagi beberapa data sensitif yang disertai dengan serialisasi.

setzamora
sumber
7
Ada kasus penggunaan selain data sensitif di mana Anda mungkin tidak ingin membuat serial suatu bidang. Sebagai contoh, Anda mungkin tidak akan pernah ingin membuat serial Thread(kredit ke @AH misalnya), dalam hal ini Anda akan menandainya sebagai sementara. Namun, utas bukan data sensitif dalam dan dari dirinya sendiri, itu hanya tidak masuk akal logis untuk membuat cerita bersambung (dan itu tidak bisa serial).
glen3b
1
@ glen3b Kasing itu tidak dikecualikan oleh jawaban ini. Ini tentu diperlukan karena ada beberapa hal dalam poster yang disebutkan.
Marquis of Lorne
3

Sesuai google makna sementara == hanya berlangsung untuk waktu yang singkat; tidak permanen.

Sekarang jika Anda ingin membuat apa pun sementara di java gunakan kata kunci sementara.

T: di mana harus menggunakan transient?

A: Secara umum di java kita bisa menyimpan data ke file dengan memperolehnya dalam variabel dan menulis variabel itu ke file, proses ini dikenal sebagai Serialisasi. Sekarang jika kita ingin menghindari data variabel untuk ditulis ke file, kita akan menjadikan variabel itu sementara.

transient int result=10;

Catatan: variabel transien tidak bisa lokal.

Mateen
sumber
0

Sederhananya, kata kunci java sementara melindungi bidang dari Serialize sebagai bagian penghitung bidang non-transien mereka.

Dalam potongan kode ini BaseJob abstrak kelas kami mengimplementasikan antarmuka Serializable, kami memperluas dari BaseJob tetapi kami tidak perlu membuat serial sumber remote dan sumber data lokal; serialkan hanya bidang organisasiNama dan 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;

   }
}
nyulan
sumber
0

Kode contoh sederhana untuk kata kunci sementara.

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);
    }
}
Habeeb Perwad
sumber
0

Bidang yang dideklarasikan dengan pengubah sementara tidak akan mengambil bagian dalam proses serial. Ketika suatu objek diserialisasi (disimpan dalam keadaan apa pun), nilai bidang transiennya diabaikan dalam representasi serial, sedangkan bidang selain bidang transien akan mengambil bagian dalam proses serialisasi. Itulah tujuan utama kata kunci sementara.

Vishal Sheth
sumber