Javaのシリアライズにおけるtransientキーワードの仕組みを解説
Javaにおけるシリアライズ(直列化)とは、オブジェクトの状態をバイトストリームに書き出すための仕組みです。これにより、オブジェクトをネットワーク越しに転送したり、ファイルに保存して後から復元したりすることが可能になります。実際の開発では、JPAやRMIといった技術と組み合わせて利用されるのが一般的です。
transient変数とは何か
transient修飾子を付けた変数は、シリアライズの対象から除外されます。つまり、transient宣言されたフィールドの値は保存されず、デシリアライズ(逆直列化)後には必ずデフォルト値(参照型ならnull、boolean型ならfalse、数値型なら0)に戻ります。
したがって、オブジェクトをシリアライズする際に、特定のインスタンス変数だけをJVMに無視させたい場合は、その変数にtransientを宣言すればよいのです。
public transient int limit = 55; // 永続化されない public int b; // 永続化される
transientが使われる主なケース
- パスワードなど、セキュリティ上の理由でシリアライズすべきでない機密情報
- 実行時に再取得・再計算できるキャッシュや一時的な計算値
- スレッドやストリームなど、本来シリアライズに適さないオブジェクトのフィールド
サンプルコード
以下のJavaプログラムでは、Studentクラスがnameとageという2つのインスタンス変数を持ち、ageにはtransientが宣言されています。別クラスのSerializeExampleでは、Studentオブジェクトをシリアライズした後、デシリアライズして各フィールドの値を表示します。ageはtransientによって隠されているため、復元後の出力ではnameだけが元の値を保ち、ageはデフォルト値の0になっていることが確認できます。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Student implements Serializable {
private String name;
private transient int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Name: "+this.name);
System.out.println("Age: "+this.age);
}
}
public class SerializeExample {
public static void main(String args[]) throws Exception {
// Studentオブジェクトの生成
Student std = new Student("Sarmista", 27);
// オブジェクトのシリアライズ
FileOutputStream fos = new FileOutputStream("e:\\student.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(std);
oos.close();
fos.close();
System.out.println("Values before de-serialization: ");
std.display();
System.out.println("Object serialized.......");
// オブジェクトのデシリアライズ
FileInputStream fis = new FileInputStream("e:\\student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Student deSerializedStd = (Student) ois.readObject();
System.out.println("Object de-serialized.......");
ois.close();
fis.close();
System.out.println("Values after de-serialization");
deSerializedStd.display();
}
}
実行結果
Values before de-serialization: Name: Sarmista Age: 27 Object serialized....... Object de-serialized....... Values after de-serialization Name: Sarmista Age: 0
この実行結果から、シリアライズ前は「Name: Sarmista / Age: 27」と表示されていた値が、デシリアライズ後にはageだけが0にリセットされていることが分かります。これこそが、transientキーワードによって当該フィールドがシリアライズ対象から除外された証拠です。機密情報や一時的なデータを持つクラスを設計する際には、transientの活用を検討するとよいでしょう。
-
Javaで可変オブジェクトの参照を含む不変クラスを作成する方法
不変(イミュータブル)オブジェクトとは、一度初期化された後はその状態を変更できないオブジェクトのことです。システムの要件によっては、独自の不変クラスを作成する必要があります。例えば、Javaのすべてのプリミティブ型ラッパークラス(Integer、Byte、Long、Float、Double、Character、Boolean、Short)は不変であり、Stringクラスも代表的な不変クラスとして知られています。 カスタム不変クラスを作成するための手順 クラスを final として宣言し、サブクラスによる拡張を防ぎます。 すべてのフィールドを private にし、外部からの直接アクセスを禁止
-
JavaオブジェクトをJSONに変換する方法(Jackson・Gsonの使い方)
このチュートリアルでは、JavaオブジェクトをJSON形式に変換する方法を、定番ライブラリであるJacksonとGsonの2つを使って解説します。 サンプルとして使用するのは、ごく標準的なPOJO(Plain Old Java Object)であるPersonクラスです。Personオブジェクトを作成したら、それぞれのライブラリを使ってJSONへ変換してみましょう。 Person.java import java.util.List; import java.util.Map; public class Person { String name; Integer age;