• 締切済み

java 直列化

javaの勉強を始めて4ヶ月になります。 それまでは、プログラミングの経験が皆無に等しいレベルです。出来れば下記の内容について解りやすく教えていただければ有難いです。 プログラム public static Category getCategory()throws・・・ String className="パッケージ名.category.class"; Class categoryClass=Class.forName(className); return (Categroy).categoryClass.newInstanse(); 質問1.上記のプログラムでインスタンス化が行えるのですか?→Category 参照変数 = new Category(); と同じ意味ですか? 質問2.もし同じ意味なら、なぜこのように周りくどいことをするのですか? 質問3.forName(),newInstance()メソッドをAPIで調べるとSerializeインターフェイスというキーワードが出できます。Serializeインターフェイスを調べると、長々と次数十項目にも及ぶ説明がされています。この説明を読んでも理解が出来ません。完結に直列化とはどういう意味か教えて頂ければ有難いです。 以上よろしくお願い致します。

みんなの回答

  • UKY
  • ベストアンサー率50% (604/1207)
回答No.3

質問の中身とは関係ありませんが、質問者さんのプログラムにちょっと誤りがあるので訂正させてください。 public static Category getCategory() throws …… { String className = "パッケージ名.Category"; Class categoryClass = Class.forName(className); return (Category) categoryClass.newInstance(); } さて、「直列化」という表現ですが、オブジェクトをバイト列のデータに変換することだと思ってください。つまり、オブジェクトを0と1が並んだデータに変換するのです。 例えば、テキスト文書ファイルをコンピュータに保存するとき、文書中の文字そのものがディスクに書き込まれるわけではありませんね。代わりに、一つ一つの文字に対応した「文字コード」のデータ(これはあくまでも0と1が並んだデータに過ぎません)が保存されます。これと同じようなことをプログラムの中のオブジェクトに対して行うようなものなのです。 もちろん、このデータは人間が直接読むことができるようなものではありません。しかし、ポイントは直列化したデータからもとのオブジェクトを復元できる、というところにあります。 これによって、ファイルに直列化データを保存しておいて、後で再びプログラムを実行したときに前とまったく同じ状態のオブジェクトを扱うとか、ネットワークでデータを転送して別のコンピュータでも同じ状態のオブジェクトを扱う、ということができるわけです。

dellfie
質問者

お礼

誠に丁寧な、ご回答ありがとうございます。3人の方から親切な回答を頂きビックリしています。実はこのGooのサービスを使うのは始めてで、こんなに反応が良いとは思っていませんでした。また、Javaの壁らしきもに当たって基本的な教科書レベルから未だ抜け出せずにいます。ちょっと挫折気味でした。直列化の件ですがなんとなく理解できたような気がします。簡単なプログラムを書いて色々と試したと思っています。今後ともよろしくお願いします。

  • naitie
  • ベストアンサー率30% (18/60)
回答No.2

プログラムって難しいですよね。初めて4ヶ月だとこういうことが解らなくて当然です。頑張ってくださいね。 質問1) 一字一句合っているかわかりませんが、インスタンス化できます。new Category()と同意です。 質問2) クラスをforName()を使ってインスタンス化するのは少し高度なプログラミングになります。プログラムをコンパイルする時点では、どのクラスを使うかが決まっていない場合に使用します。 それがどんな時かが重要ですが、例えば、あなたが画像を画面に表示するプログラムを作ったとします。画像ファイルにはいろんな形式(jpg,png,tif,etc..)があり、全部に対応するのは大変なので、とりあえずjpgとtifを表示するクラスを作成しました。画像がjpgなら JPGView、tifならTIFFView といった具合に。これらのクラスを、下記のように「呼び出しクラス」に静的に組み込むと、 _if (fileTyle == JPG) __viewer = new JPGView(); _else _if (fileType == TIF) __viewer = new TIFView(); __viewer.view(); // 画像を表示! 後であなたがヒマになって、png形式に対応したときに、この「呼び出しクラス」のif~else のブロックに、 : _else _if(fileType == PNG) __viewer = new PNGView(); _viewer.view() // 画像を表示! を追加して再コンパイルしないといけません。こうなると、あなたのプログラムを買った全員が「呼び出しクラス」まで入替えないとpngが使えなくなります。 これを、設定ファイルやレジストリなどに例えば、   viewclass.PNG=PNGView; と一行追加して、PNGViewクラスだけを入手するだけでPNGが表示できれば便利ですよね。こうするには、いわゆるプラグインってやつです。「呼び出しクラス」は普通プログラム本体でサイズが大きく、~Viewクラスは部品でサイズが小さくなります。こうしたければforName()は必須になりますよね。 質問3) 「直列化」の意味はとても簡単ですが、Javaの文書を見ると本当に難しいですよね・・・・。後で説明しますが、互換性の問題があって、それだけ実装(作る側)には難しい問題なのです。 例えば、あるクラスの配列 array があって、arrayには a,b,cの3つのインスタンスの参照が入ってます。a, b, cはメモリ上では、つながって並んでいる保証はなく、おそらくばらばらに散らばっています。arrayは、a, b, cそれぞれの場所を、[100番地, 232番地、620番地]といったふうに覚えています。この配列 arrayをファイルに書き込んだり、通信ストリームとして通信先に渡すことを考えましょう。それがシリアライズ(直列化)です。読んで字の如くですよね。 ファイルに書きたければとうしますか?[100番地, 232番地、620番地]と書いて終り・・これは明らかにNGですよね。次にファイルを開けても、aもbもcも無いのですから。じゃあそれに加えてファイルの該当番地にばらばらにa, b, cを書き込むのでしょうか・・。それもNGです。a,b,c しか必要ないファイルが凄く大きくなってしまいます。結局、arrayは随分形を変える(例えば、「続く3つのオブジェクトが僕の管理している要素です」などの情報を書き込んでa,b,cと連続で並べる)必要があります。読み込む時は、その逆が必要ですよね。a,b,cをそれぞれ読んで、メモリ上に別々に格納する必要があります(当然番地は変わります)。 このように、ファイルなど「ストリーム」と呼ばれるシリアルな(一本の)線上に、必要なデータを書き込んだり、読み込んだりする処理をシリアライズといいます。 配列だと容易に想像できますが、これがツリーやマップなどデータ構造が複雑になれば「どうやってシリアライズされてるんだ??」といった難しい問題になります。 あとシリアライズの説明が難しくなるのは、互換性を考える必要があるからです。昔のプログラムがファイルに書いた array を、最新のプログラムでも読めなくてはいけません。javaがバージョンアップに伴いシリアライズの実装が変更されて、書かれたデータの内容が変わっても、昔に書かれた array が読めなくては、世間から悲鳴が上がります。 大変ですよ。この仕事は・・・。

dellfie
質問者

お礼

ご回答ありがとうございます。No3の方の「お礼」欄にまとめて、お礼を書かせて頂きました。

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.1

質問1  結果としては同じことになりますね。 質問2  forName().newInstance()とすることで、  生成するインスタンスを、実行時に動的に変えることができます。  たとえば、ユーザが入力したクラス名を動的にnewするとしたら、  Category 参照変数 = new Category();  こういう書き方では対処できませんよね。 質問3  これは私も詳しくは説明できてないかも知れませんが、  オブジェクトの状態を全部書き出すことだと思っています。  たとえば、「あるクラスHogeのインスタンスhが、  f1,f2というフィールドを持っていて、f1=1, f2=2という状態だ。」  ということを全部書き出します。  この書き出した情報を、ネットワーク経由で送信して、  受信した側で復元すると、元と同じものが作り出せるみたいな。  標準のクラスの大部分はSerializableインターフェースを実装しています。  これは直列化可能のクラスであることを意味しています。  ObjectOutputStreamを使って、直列化したり、  ObjectInputStreamを使って、復元してみたりすると  動作がわかると思います。

dellfie
質問者

お礼

ご回答ありがとうございます。No3の方の「お礼」欄にまとめて、お礼を書かせて頂きました。