- ベストアンサー
Class.forName("Hogehoge")の使い方
Class.forName("Hogehoge");は 動的にクラス(この例では"Hogehoge")をロードする場合に使用するとの説明が当Q&Aに記載されていましたが、次のコーディング例が有りました。 Hogehoge hh = Class.forName("Hogehoge").newInstance(); この例では、リターンを受けるクラス名が、動的に指定されていないため、具体的な利用方法が分かりませんでした。 よろしく、ご教示いただければ幸甚です。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
#2です。 >Menuにクラス名を登録しておき、指定されたMenuのクラスをスタートするような ことを考えていました。 1つのメニュー項目(メニュー機能)に1つのクラスを対応させ、 選択されたメニュー項目に対応したクラスを実行するわけですね。 その場合、それらのクラスには全て「メニュー項目になる」という共通点がありますね? その共通点をインターフェースとして定義しておきます。 interface IMenuItem { /** メニュー項目の名前*/ public String getCommandName(); /** メニュー項目の実行*/ public void execute(); } 全てこのインターフェースを実装して下さい。 また、実行時には Class cls = Class.forName(className); IMenuItem menuItem = (IMenuItem)cls.newInstance(); menuItem.execute(); となります。
その他の回答 (5)
- ngsvx
- ベストアンサー率49% (157/315)
#5です。もう少し、補足しておきます。 前回も示した通り、Class.forName("").newInstance()で受ける型は、 ある程度限定して使うことがほとんどです。 逆に、限定しない(Object型で受ける)ということは、 インスタンスを生成した後に実行させること(実行させる目的)も はっきりしていないということになります。 (前回の例では、メニュー項目を実行させる目的で、インスタンスを生成したわけです。) ほとんどの場合、クラスをインスタンス化するには、何らかの目的があるはずですから、 その目的をグループ化したクラス等で受ければいいわけです。 あまり考えられませんが、インスタンス化するクラスが、 ・Stringだったらlength()を実行 ・ArrayListだったらsize()を実行 などのように、全く関係ないクラスがインスタンス化される可能性がある場合は、 Object obj = Class.forName(className).newInstance(); のように、Object型で受ければOKです。 その後、 if(obj instanceof String){ String s = (String)obj; System.out.println("length=" + s.length() ); }else if(obj instanceof ArrayList){ ArrayList list = (ArrayList)obj; System.out.println("size=" + list.size() ); } のようになります。 ですから、受けるクラス名が動的に指定されなくても問題はありません。
- kacchann
- ベストアンサー率58% (347/594)
>リターンを受けるクラス名が、動的に指定されていないため、具体的な利用方法が分かりませんでした >Class.forNameのパラメータが動的に指定できるとき、 受け入れるクラス名を動的に指定できないのであれば、結果的に動的にクラスを生成できないのでは Fooというクラスの変数 Foo f; があった場合、fに代入できるインスタンスは 「Fooクラスのインスタンス」 のみならず、 「『Fooを継承しているサブクラス』のインスタンスすべて」 が代入可能。(スーパークラス型への代入) また、Fooというのが(クラス名でなく)インターフェース名だった場合、 Foo f; なる変数fに代入できるのは、 「『インターフェースFooをインプリメント(実装)しているクラス』のインスタンスすべて」 が代入可能。(インタフェース型への代入) ---- つまり、上記の2通りのいずれかを満たしていれば、 代入先の変数の「型」の名前が固定されていても、 そこに代入するインスタンス(のクラス)は動的に「選べる」ことになる。 Javaの「多態(ポリモーフィズム)」について調べみよう。 この辺の話をわかりやすく解説しているはずだ。 Javaプログラミングにおける超基本事項であり、 最重要事項の1つでもある。 ------ ↓実験すべし import java.awt.*; public class Test { public static void main(String[] args) { String s; if ("a".equals(args[0])) { s = "java.awt.Rectangle"; } else if ("b".equals(args[0])) { s = "java.awt.Frame"; }else { s = "java.awt.Point"; } Object o=null; try { o = Class.forName(s).newInstance();//※ }catch(Exception e) {e.printStackTrace();} System.out.println(o); } }
お礼
有難うございました。 urlの紹介もいただき有効活用させていただきます。
- lawson
- ベストアンサー率44% (29/65)
思いつく例を 2点挙げます まず、1つ目 No1で例にあげられたドライバーのクラス名が プロパティーファイルに記述されている ようなケースでは、 Class.forNameを使って動的にする以外に 方法がない。 2つ目 抽象クラス ItemFactoryの中で this.getClass().getName() で得られる自身のクラス名の 「Factory」という文言を「Product」 に変えたクラスのインスタンスを Class.forName( を使ったやり方で 生成する コードがあるメソッドがあったとして。 継承クラス ItemFactoryAクラスにおけるそのメソッドの 挙動としては、 ItemProductAクラスのインスタンスを 生成する。 継承クラス ItemFactoryBクラスにおけるそのメソッドの 挙動としては、 ItemProductBクラスのインスタンスを 生成する。 なぜなら、 this.getClass().getName() の部分の thisは実行時の ItemFactoryAや ItemFactoryBの インスタンスだから。
お礼
Menuにクラス名を登録しておき、指定されたMenuのクラスをスタートするようなことを考えていました。 お教えを参考にさせていただきます。 有難うございました。
- ngsvx
- ベストアンサー率49% (157/315)
まず、確認をしておきましょう。 Class.forName("Hoge").newInstance(); というのは、 Class cls = Class.forName("Hoge"); Hoge hg = (Hoge)cls.newInstance(); と同じ意味で、さらに Hoge hg = new Hoge(); と同じ意味です。 また、インスタンス生成時にタイプを限定したくないのであれば、 Class cls = Class.forName("Hoge"); Object hg = cls.newInstance(); となります。 指定したオブジェクトのクラス名を知りたいなら、 Hoge hg = new Hoge(); Class cls = hg.getClass(); System.out.println(cls.getName()); でOKです。 *何が知りたいのかよくわからなかったので、 いっぱい書いてしまいました。
お礼
インスタンス生成時にタイプを限定しない方法を知りたく思っていましたので、助かりました。 有難うございました。
- jun-1
- ベストアンサー率29% (18/61)
java.sql.Driverクラスなんかのインスタンスを生成 する場合なんかによく使ったりします。 ・ ・ OracleDriver driver = (Driver)Class.forName("oracle.jdbc.driver.OracleDriver").newInstnace(); ・ ・ そのほかにも動的にクラスが生成できるため、FactoryMethod パターンなんかにも適応できると思います。
補足
Class.forNameのパラメータが動的に指定できるとき、 受け入れるクラス名を動的に指定できないのであれば、結果的に動的にクラスを生成できないのではと考えています。 例えば、次のような使い方が出来ないのかお教えいただきたいのです。よろしくご教示下さい。 String strClassW; String strClassA "ClassA"; String strClassB "ClassB"; if (arg[0].equals("a")) { strClassW = strClassA; } else { strClassW = strClassB; } 以下の表記はjavaで許されるものではないと思いますが、 Class(strClassW) class = Class.forName(strClassW).newInstance(); System.out.println(class.toString());
お礼
有難うございます。 目から鱗の思いです。