• 締切済み

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インターフェイスを調べると、長々と次数十項目にも及ぶ説明がされています。この説明を読んでも理解が出来ません。完結に直列化とはどういう意味か教えて頂ければ有難いです。 以上よろしくお願い致します。

  • Java
  • 回答数3
  • ありがとう数9

みんなの回答

  • 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の方の「お礼」欄にまとめて、お礼を書かせて頂きました。

関連するQ&A

  • サブクラスで.newInstance()でインスタンス化できない

    以下のようにClass.forNameで取得したクラスをインスタンス化 しようとしていますが、できません サブクラスは.newInstance()でインスタンス化できないのでしょうか? 代替の方法はありますか? ーーーーーーーーーーーーーーーー public class test4121 { public static void main(String[] args) throws Throwable { new test4121(); } public test4121() throws Throwable { //これは実行できるが test4121_2 test = new test4121_2(); //これはできない Class.forName("test4121$test4121_2").newInstance(); } class test4121_2{ } } ーーーーーーーーーーーーーーーー

  • JDBCドライバーのロードに関して

    参考書やwebページのソースコードにJDBCドライバーのロードのときに、Class.forName("...")と書いているものと、Class.forName("...").newInstance()と書いているものがあります。[...部分は省略]この二つのコードは、どこが違うのでしょうか。また、Sunmicroのホームページで、forNameメソッドは、"指定された文字列名を持つクラスまたはインタフェースに関連付けられた、Class オブジェクトを返します。"と、newInstanceメソッドは、"この Class オブジェクトが表すクラスの新しいインスタンスを生成します。"と書かれていますが、どうしてこれで、JDBCドライバーがロードされるのですか?また、初歩的な質問ですが、JDBCドライバーがロードされるというのは、どうゆうことですか?教えてください。

    • ベストアンサー
    • Java
  • Class.forName("org.postgresql.Driver")の意味

    JDBCを使って、PostgreSQL を利用する場合、 まず最初に、Class.forName("org.postgresql.Driver")というのを使いますよね。 この、Class.forName(String str)メソッドは、str にある、クラスを初期化すると仕様書には書いてます。 (Class.forName("org.postgresql.Driver")).newInstance() を実行して、org.postgresql.Driver.class のコンストラクタを実行するというのなら、意味はわかるのですが、、、 ただClass.forName("org.postgresql.Driver")の命令だけを使ってなんの意味があるのでしょうか? 意味不明で困っています。どうか、よろしくお願い致します。

    • ベストアンサー
    • Java
  • 指定されたクラスの継承元の確認方法

    Class cls = Class.forName("extendsClass"); Object obj = cls.newInstance(); if (obj instanceof AbstractClass) {   System.out.println("継承してた");   ((AbstractClass)obj).method(); } こんなことをして、objのクラスがAbstractClassを継承しているという ことは確認することが出来たのですが、これはやはり継承しているか どうかを確認する為にインスタンス化を行っています。 指定された名称のクラスが、特定のクラスを継承していた場合に限り、 その名称のクラスをインスタンス化する、 という流れは行えないのでしょうか?

    • ベストアンサー
    • Java
  • 同一クラスインスタンス名で別クラスのインスタンス作成方法(C++)

    下記ソース(Java)の処理をするような、C++の実装方法を教えていただきたいです。 【処理内容】 クラスBのインスタンスを保持しており、クラスBのインスタンス名と同一であるクラスAのインスタンス生成 ClassA A_Instance = (ClassA)Class.forName(B_instance.name).newInstance(); 要はクラスインスタンスの名前の求め方がわからないのです。それさえわかれば、newしてクラスポインタを返すメソッドを用意すれば何とかなると考えていますが。 ※C++のAPI一覧はどこにあるのだろうか・・・

  • Class.forName("Hogehoge")の使い方

    Class.forName("Hogehoge");は 動的にクラス(この例では"Hogehoge")をロードする場合に使用するとの説明が当Q&Aに記載されていましたが、次のコーディング例が有りました。 Hogehoge hh = Class.forName("Hogehoge").newInstance(); この例では、リターンを受けるクラス名が、動的に指定されていないため、具体的な利用方法が分かりませんでした。 よろしく、ご教示いただければ幸甚です。

    • ベストアンサー
    • Java
  • JavaでのXMLデータ抽出について

    いつも、お世話になります。 以前、Perlでも似たような質問をさせていただきましたが、結局、Javaで作ることになりました。ところが、以下の現象が発生して困っております。 プログラムは、下記のXmlファイルを読み込ませ"★"の部分を抽出してくるというプログラムです。 読み込んだ結果として、次のようなものが欲しいとすると、 memoNumber = Class_A MemoNumber = 53 memoNumber = Class_B MemoNumber = 67 : 実際には、以下のようになってしまいます。 memoNumber = Class_A MemoNumber = 53 memoNumber = Class_A MemoNumber = 42 : つまり、"memoNumber"の最初の要素しか見ておらず、次の"MemoNumberList"以下のタグ内を探しに行ってしまうようです。 そこまでは分かったのですが対処法法が分かりません。 読み込ませたいXMLファイルは以下のとおりです(データ数が膨大になるので一部省略をしています) <MemoBlockList> <Class ID="namae1" >★ <Local>1</Local> <AmemoWritingLocationList> <AmemoWritingLocation Length="50" Side="1">★ <CreateID>345.9886776</CreateID> <IDList> <IDNo IDNo="1">★ <MemoNumberList> <MemoNumber memoNumber="Class_A">53</ClassName>★ <MemoNumber memoNumber="Class_B">67</ClassName>★ <MemoNumber memoNumber="Class_C">88</ClassName>★ <MemoNumber memoNumber="Class_D">00</ClassName>★ <MemoNumber memoNumber="Class_E">32</ClassName>★ </MemoNumberList> </IDNo> </IDList> <IDNo IDNo="2">★ <MemoNumberList> <MemoNumber memoNumber="Class_A">42</ClassName>★ <MemoNumber memoNumber="Class_B">90</ClassName>★ <MemoNumber memoNumber="Class_C">101</ClassName>★ <MemoNumber memoNumber="Class_D">978</ClassName>★ <MemoNumber memoNumber="Class_E">21</ClassName>★ </MemoNumberList> </IDNo> </IDList> <IDNo IDNo="3">★ <MemoNumberList> <MemoNumber memoNumber="Class_A">10</ClassName>★ <MemoNumber memoNumber="Class_B">1</ClassName>★ <MemoNumber memoNumber="Class_C">11</ClassName>★ <MemoNumber memoNumber="Class_D">99</ClassName>★ <MemoNumber memoNumber="Class_E">66</ClassName> </MemoNumberList> </IDNo> </IDList> </AmemoWritingLocation> <location>15</location> </AmemoWritingLocationList> </MemoBlock> </MemoBlockList> Javaのソースは以下のとおりです。 import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.*; public class MemoBlecks { public static void main(String[] args) { try { DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbfactory.newDocumentBuilder(); Document doc = builder.parse(new File("MemoBlock.xml")); Element root = doc.getDocumentElement(); System.out.println("ルート要素のタグ名:" + root.getTagName()); System.out.println("***** 値リスト *****"); System.out.println("要素:memoNumberList"); System.out.println("値:MemoNumberList"); NodeList list = root.getElementsByTagName("MemoNumberList"); for (int i=0; i < list.getLength() ; i++) { Element element = (Element)list.item(i); String MemoNumber = element.getAttribute("memoNumber"); NodeList MemoNumberList = element.getElementsByTagName("MemoNumber"); Element MemoNumberElement = (Element)MemoNumberList.item(0); String MemoNumber = MemoNumberElement.getFirstChild().getNodeValue(); System.out.println("memoNumber="+memoNumber); System.out.println("MemoNumber="+MemoNumber); } } catch (Exception e) { e.printStackTrace(); System.out.println("このウィンドウ上で次の操作を実行してください..."); System.out.println("「右クリック→すべて選択→右クリック→テキストエディタを開き、evaluation.txtとして保存」"); } } } 開発環境は次のとおりです。 OS:WindowsXP HomeEdition SP2 Java:JDK1.6.0_04 Javaに関しては初心者レベルの知識しかありません。そのため、載せたものも少々おかしいですが、どなたかご教授のほどお願い致します。

    • ベストアンサー
    • Java
  • 抽象クラスが継承されているかどうか検証したい

    Class.forName()にて取得したクラスが、特定の抽象クラスを継承しているかどうかを 検証したいです。 Class.getInterfaces()にて、実装されているインターフェースを取得することが出来ましたが、 Class.getClasses()、Class.getDeclareClasses()のいずれでも、継承されている 抽象クラスを取得することが出来ません。 そもそも抽象クラスはインスタンス化できないからなのかもしれませんが、 ならば、その抽象クラス名称を取得したいです。 方法はありますでしょうか? 無理ならばインターフェースの実装にし、基盤部で動作のカバーを する作りで考え直すつもりです。

    • ベストアンサー
    • Java
  • JDBC ドライバーのロードの方法について

    すみませんが、どなたか教えていただけないでしょうか。 JDBCを使ってデータベースにアクセスしようとする場合に、まずドライバーのロードが必要ですが、 1.Class.forName("ドライバー名"); 2.Class.forName("ドライバー名").newInstance(); 1の方法と2の方法の違いは何かあるのでしょうか?今まで私は1の方法を使っていたのですが、2の方法があると知り、どのようなときに使うものなのかわかりません。このようなときにはこっちを使う、というようなルールや目安などありましたら、教えていただけますでしょうか。 ちなみに私は、データベースはDB2を使っています。 ↓また、以前に似たような(?)質問も見受けられたのですが、私にはちょっと難しくて理解できませんでした… http://okweb.jp/kotaeru.php3?q=642489 どうぞよろしくお願いいたします。

    • ベストアンサー
    • Java
  • Javaについて

    Javaについての質問です。 下記のプログラムは Abst_Class show1 can be inheritted to a subclass num1=1 Class1 show2 is created in Class1 num1=1 num2=2 Class2 show1 is inheritted and overridden in Class2 num1=10 str=SSSSSS Class2 show2 is created in Class2 num1=10 str=SSSSSS と出力するプログラムなのですがエラーが出て出力できません。どこがいけないのか教えていただけないでしょうか? お願いいたします。 interface itr{ itr(){} void show(); void dai(); } abstract abr implements itr{ abr(){ int num1; num1=1; } public void dai(){ if(num1==0){ num1=1; } } public void show(){ dai(); System.out.println("Abst_Class show1 can be inheritted to a subclass num1="+num1); } abstract show1(); } class Class1 extends abr{ int num2; Class1(int a,int b){ num1=a; num2=b; } public void show1(){ super.show(); } void show2(){ super.show(); System.out.println("Class1 show2 is created in Class1 num1="+num1+"num2="+num2); } } class Class2 extends abr{ String str; Class2(int num,String str){ this.str=str; num1=num; } public void show1(){ System.out.println("Class2 show1 is inheritted and overridden in Class2 num1="+num1+"str="+str); } void show2(){ System.out.println("Class2 show1 is inheritted and overridden in Class2 num1="+num+"str="+str); } } class K10_6{ public static void main(String args[]){ Class1 f1 = new Class1(1, 2); Class2 f2 = new Class2(10,"SSSSSS"); f1.show1(); f1.show2(); f2.show1(); f2.show2(); } } .\abr.java:1: class、interface、または enum がありません。 abstract abr implements itr{ ^ .\abr.java:4: class、interface、または enum がありません。 num1=1; ^ .\abr.java:5: class、interface、または enum がありません。 } ^ .\abr.java:6: class、interface、または enum がありません。 public void dai(){ ^ .\abr.java:9: class、interface、または enum がありません。 } ^ .\abr.java:11: class、interface、または enum がありません。 public void show(){ ^ .\abr.java:13: class、interface、または enum がありません。 System.out.println("Abst_Class show1 can be inheritted to a subclass num1="+num1 ); ^ .\abr.java:14: class、interface、または enum がありません。 } ^ .\abr.java:15: class、interface、または enum がありません。 abstract show1(); ^ .\abr.java:16: class、interface、または enum がありません。 }

    • ベストアンサー
    • Java

専門家に質問してみよう