Java に一時フィールドがあるのはなぜですか?
15 に答える
Javaのtransient
キーワードは、フィールドがシリアライゼーション (ファイルのように保存されることを意味します) プロセスの一部であってはならないことを示すために使用されます。
Java 言語仕様、Java SE 7 Edition、セクション 8.3.1.3transient
から。フィールド:
Variables may be marked
transient
to indicate that they are not part of the persistent state of an object.
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 GalleryImage
class which contains an image and a thumbnail derived from the image:
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 thumbnailImage
is a thumbnail image that is generated by invoking the generateThumbnail
method.
thumbnailImage
フィールドは としてマークされているため、元の画像とサムネイル画像の両方を保持するのではなく、元の画像のみがシリアル化されますtransient
。image
これは、シリアル化されたオブジェクトを保存するために必要なストレージが少なくなることを意味します。(もちろん、これはシステムの要件に応じて望ましい場合とそうでない場合があります。これは単なる例です。)
逆シリアル化の時点で、readObject
メソッドは、オブジェクトの状態をシリアル化が発生した状態に復元するために必要な操作を実行するために呼び出されます。ここでは、サムネイルを生成する必要があるため、readObject
メソッドを呼び出すことでサムネイルが生成されるようにメソッドをオーバーライドしgenerateThumbnail
ます。
詳細については、記事Discover the secrets of the Java Serialization 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
いるため、永続ストレージには保存されません。
シリアライズしたくない変数を定義できるようにします。
オブジェクトには、シリアル化/永続化したくない情報 (おそらく親ファクトリ オブジェクトへの参照) がある場合や、シリアル化する意味がない場合があります。これらを「transient」としてマークすると、シリアライゼーション メカニズムがこれらのフィールドを無視することになります。
transient
変数は、クラスがシリアル化されるときに含まれない変数です。
これが役立つ場合の 1 つの例として、特定のオブジェクト インスタンスのコンテキストでのみ意味を持ち、オブジェクトをシリアル化および逆シリアル化すると無効になる変数があります。null
その場合、必要に応じて有用なデータで再初期化できるように、これらの変数を代わりに使用すると便利です。
transient
クラス フィールドをシリアル化する必要がないことを示すために使用されます。おそらく最も良い例はThread
フィールドです。Thread
その状態は非常に「フロー固有」であるため、通常、 a をシリアライズする理由はありません。
この質問に答える前に、シリアル化について説明する必要があります。科学計算機でのシリアル化の意味を理解していれば、このキーワードは簡単に理解できるからです。
オブジェクトがネットワーク経由で転送されたり、物理メディア (ファイルなど) に保存されたりする場合、オブジェクトは「シリアル化」されている必要があります。シリアル化は、バイト ステータス オブジェクトの系列を変換します。これらのバイトはネットワーク上で送信/保存され、オブジェクトはこれらのバイトから再作成されます。
例:
public class Foo implements Serializable
{
private String attr1;
private String attr2;
...
}
このクラスに転送または保存したくないフィールドがある場合は、transient
キーワードを使用できます
private transient attr2;
これにより、クラスがシリアル化されるときにフィールド フォームが含まれなくなります。
すべての変数が直列化可能な性質を持つわけではないため
シリアル化に伴う機密データを共有したくない場合に必要です。
Google の一時的な意味 == 短時間だけ続く; 永久的でない。
Javaで何かを一時的にしたい場合は、transientキーワードを使用してください。
Q: どこでトランジェントを使用しますか?
A:一般に Java では、データを変数で取得し、それらの変数をファイルに書き込むことでデータをファイルに保存できます。このプロセスはシリアライゼーションとして知られています。ここで、変数データがファイルに書き込まれるのを避けたい場合は、その変数を一時的なものにします。
transient int result=10;
注:一時変数をローカルにすることはできません。
簡単に言えば、一時的な 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;
}
}