回答:
transient
Java のキーワードは、フィールドがシリアル化(ファイルのように保存されることを意味する)プロセスの一部であってはならないことを示すために使用されます。
Java言語仕様のJava SE 7版、セクション8.3.1.3。transient
分野:
変数にマーク
transient
を付けて、オブジェクトの永続的な状態の一部ではないことを示すことができます。
たとえば、他のフィールドから派生したフィールドがあり、シリアル化によって状態を保持するのではなく、プログラムでのみ実行する必要がある場合があります。
以下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
メソッドを呼び出すことでサムネイルが生成されるようにします。
追加情報については、JavaシリアライゼーションAPIの記事(Sun Developer Networkで最初に公開されました)の秘密の発見に、transient
特定のフィールドのシリアライゼーションを防ぐためにキーワードを使用するシナリオを示すセクションがあります。
transient
キーワードを理解する前に、シリアル化の概念を理解する必要があります。読者がシリアル化について知っている場合は、最初のポイントをスキップしてください。
シリアライゼーションは、オブジェクトの状態を永続化するプロセスです。これは、オブジェクトの状態がバイトのストリームに変換され、永続化(ファイルへのバイトの格納など)または転送(ネットワークでのバイトの送信など)に使用されることを意味します。同様に、逆シリアル化を使用して、オブジェクトの状態をバイトから戻すことができます。シリアライゼーションは主にネットワークプログラミングで使用されるため、これはJavaプログラミングの重要な概念の1つです。ネットワーク経由で送信する必要があるオブジェクトは、バイトに変換する必要があります。そのためには、すべてのクラスまたはインターフェースがインターフェースを実装する必要がありSerializable
ます。これは、メソッドのないマーカーインターフェイスです。
transient
キーワードとその目的は何ですか?デフォルトでは、オブジェクトのすべての変数が永続的な状態に変換されます。場合によっては、変数を永続化する必要がないため、一部の変数の永続化を避けたいことがあります。したがって、これらの変数をとして宣言できますtransient
。変数がとして宣言されている場合、transient
永続化されません。それがtransient
キーワードの主な目的です。
上記2点について、以下の例で説明したいと思います。
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
ため、永続ストレージには保存されません。
NameFormatter
中古車への参照があるかもしれませんtoString()
。または、データとは対照的に、構成、表示、またはビジネスロジックに関連するもの。
シリアル化したくない変数を定義できるようにするため。
オブジェクト内に、シリアル化/永続化したくない情報(おそらく親ファクトリオブジェクトへの参照)がある場合や、シリアル化しても意味がない場合があります。これらを「一時的」としてマークすると、シリアル化メカニズムがこれらのフィールドを無視します。
私の小さな貢献:
一時的なフィールドとは何ですか?
基本的に、transient
キーワードで変更されたフィールドは一時的なフィールドです。
Javaで一時フィールドが必要なのはなぜですか?キーワードは、あなたのシリアル化プロセスをある程度制御を与え、あなたは、このプロセスからいくつかのオブジェクトのプロパティを除外することができます。シリアライゼーションプロセスは、Javaオブジェクトを永続化するために使用されます。これにより、ほとんどの場合、それらの状態は、転送中または非アクティブでも保持できます。場合によっては、オブジェクトの特定の属性をシリアル化しないことが理にかなっています。どのフィールドを一時的としてマークする必要がありますか?
今、私たちはの目的を知っていますtransient
transient
キーワードと一時的なフィールドの場合、一時的なものとしてマークするフィールドを知ることが重要です。静的フィールドもシリアル化されないので、対応するキーワードも役立ちます。しかし、これはクラスの設計を台無しにするかもしれません。ここでtransient
キーワードが役に立ちます。他のフィールドから値を導出できるフィールドがシリアル化されないようにするため、一時的なものとしてマークを付けます。interest
他のフィールド(principal
、rate
&time
)から値を計算できるという名前のフィールドがある場合、それをシリアル化する必要はありません。
別の良い例は、記事の単語数です。記事全体を保存する場合は、記事が「逆シリアル化」されたときに計算されるため、実際には単語数を保存する必要はありません。またはロガーについて考えてください。Logger
インスタンスをシリアル化する必要はほとんどないため、一時的なものにすることができます。
transient
transient
transient
変数がシリアライズされない場合があり変数です。
これが役立つと思われる1つの例は、特定のオブジェクトインスタンスのコンテキストでのみ意味があり、オブジェクトをシリアル化および逆シリアル化すると無効になる変数です。その場合、それらの変数をnull
代わりにして、必要なときに有用なデータで再初期化できるようにすると便利です。
transient
クラスフィールドをシリアル化する必要がないことを示すために使用されます。おそらく最良の例はThread
フィールドです。のThread
状態は非常に「フロー固有」であるため、通常、をシリアル化する理由はありません。
A
参照直列化可能でないクラスB
(のようなThread
あなたの例では)、その後A
のいずれかの参照をマークする必要がありますtransient
XORをして、合理的な何かをするために、デフォルトのシリアル化プロセスをオーバーライドする必要がありますB
XORの唯一の直列化可能サブクラスがいることを前提としB
、実際に参照されています(したがって、実際のサブクラスは「悪い」親を処理する必要がありますB
)XORは、直列化が失敗することを受け入れます。1つだけのケース(一時的としてマークされている)B
は、自動的かつサイレントにスキップされます。
ネイティブJava以外のシリアル化システムでもこの修飾子を使用できます。たとえば、Hibernateは@Transientまたは一時的な修飾子でマークされたフィールドを永続化しません。テラコッタもこの修飾子を尊重します。
修飾子の比喩的な意味は「このフィールドはメモリ内でのみ使用することです。永続化したり、この特定のVMの外部に移動したりしないでください。その移植性はありません」です。つまり、別のVMメモリ空間でその値に依存することはできません。volatileによく似ているということは、特定のメモリやスレッドのセマンティクスに依存できないことを意味します。
transient
現時点で設計されていれば、それはキーワードにはならないと思います。彼らはおそらく注釈を使用するでしょう。
私はこの質問に応じる前に、私はあなたに説明しなければならないSERIALIZATIONをあなたはそれはあなたが簡単にこのキーワードを理解することができ、科学コンピュータ内の直列化を意味するものを理解していればいるので、。
シリアル化
オブジェクトが物理メディアに保存/ネットワークを介して転送される(ファイル、...)は、オブジェクトは、「連載」でなければなりません。シリアライゼーションは、バイトステータスオブジェクトシリーズを変換します。これらのバイトはネットワーク上で送信/保存され、オブジェクトはこれらのバイトから再作成されます。
例
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
このオブジェクトSOの転送 / 保存フィールドを実行しない場合は、キーワードを使用できます transient
private transient attr2;
シリアル化に伴う機密データを共有したくない場合に必要です。
Thread
(@ AHへのクレジットなど)をシリアル化したくない場合は、一時的なものとしてマークします。ただし、スレッド自体は機密データではないため、シリアル化しても論理的には意味がありません(シリアル化できません)。
簡単に言えば、transient javaキーワードは、非一時的なフィールドが対応するときに直列化されたフィールドを保護します。
このコードスニペットでは、抽象クラス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;
}
}
一時的なキーワードの簡略化されたサンプルコード。
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);
}
}
@DoNotSerialize
ですか?