Javaにおいて,入出力ストリームを通してオブジェクトをやり取りできるようにする仕組みを”直列化(シリアライズ)”と呼ぶそうです.ざっくり言うと,オブジェクト単位でファイルに読み書きができるようにする仕組みです.
オブジェクトを入出力するストリーム(オブジェクトストリーム)には,出力用のjava.io.ObjectOutputStreamと,入力用のjava.io.ObjectInputStreamがあります.それらを利用するには,ファイルに書き込みたいオブジェクトのクラスにSerializableインタフェースを実装する必要があります.
オブジェクトストリームを利用することで,オブジェクトのメンバ変数が読み書きされることになります.しかし,メンバ変数にtransientを指定すると,そのメンバ変数は直列化しなくなります.また,static変数も直列化しません.
直列化の具体例を次に示します.String型のメンバ変数a,b,cを持つTestClassを一度ファイルに書き込み,その後ファイルから読み込んで,それらの操作の前後におけるa,b,cの値を確かめるプログラムです.
import java.io.*; class TestClass implements Serializable { private String a; private transient String b; private static String c = "C"; public TestClass(String a, String b) { this.a = a; this.b = b; } public static void setC(String newC) { c = newC; } public void show() { System.out.println("(a, b, c) = (" + a + ", " + b + ", " + c + ")"); } } public class SerializeTest { public static void main(String[] args) { String path = args[0]; File file = new File(path); try { System.out.println("Write"); ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(file)); TestClass testClassOut = new TestClass("A", "B"); oos.writeObject(testClassOut); oos.flush(); oos.close(); testClassOut.show(); System.out.println(); TestClass.setC("D"); System.out.println("Read"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream( file)); TestClass testClassIn = (TestClass) ois.readObject(); ois.close(); testClassIn.show(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
実行結果
Write
(a, b, c) = (A, B, C)Read
(a, b, c) = (A, null, D)
メンバ変数aについてはオブジェクトの読み書きの前後で値は変わっていません.bについては,transient指定により直列化されなかったため,読み込んだ結果はオブジェクト変数の初期値であるnullとなりました.static変数cについては,書き込みと読み込みの間でcの値を変更し,読み込み終了時にcの値が書き込み時の値に戻されるかどうかを確かめましたが,戻されませんでした.これは,static変数が個々のオブジェクトに依存しないためです.