2007年8月11日土曜日

Javaプログラマ的なお話



今週は火曜日以外終電まで残業と言う惨事ですた。火曜は結婚記念日なんで脱走。





現在は詳細設計フェーズで担当コンポーネントはBeanをXMLに、XMLをBeanに変換するという内容。


成果物としてはクラス図とJavaDocを求められているのだが、チーム内にJava初心者が多いため『詳細設計でも大枠の流れ(と言いいつつ一番複雑なパターン)のコードは作れてるんだよね』と言う意味不明なリーダの発言により過酷な労働を強いられるハメに…。っつーか製造半分以上終わったぞw


コンポーネントの構造はファサードやテンプレートメソッドなどのデザインパターンを実装しており、内部ではリフレクションで動的に生成したオブジェクトに対して動的に生成したメソッドを何重もループさせるような狂気じみた構造。





でだ。それなりに経験のあるJavaプログラマならお手の物かもしれんが、経験年数1年8ヶ月のヒヨッコな俺にそんなものがホイホイ作れるわけないのだが作らされた。


その中でも一番てこずった『動的に生成したオブジェクトに対する動的に生成したメソッド』の個所を備忘録と復習を兼ねてここに記しておこう…。


っつーか検索すれば情報は山のように出てくるんだが、一番詰まった個所だけさらっと。





まず最初にクラスを生成。


Class clazz = Class.forName("パッケージ名.クラス名");


ここで注意しなければならないのが、パッケージ名.クラス名が何らかの形でコンストラクタを明示的に宣言しているかどうかという点。


例えばパッケージ名.クラス名がスーパークラスなどでコンストラクタを呼んでいる場合、単にgetDeclaredFieldsとかしてもClassオブジェクト自体のフィールドしか取って来れません。


何故ならこの時点でインスタンス化はされていないからです。多分。


コンストラクタの呼び出しはinvokeの代わりと思ってもらうと解り易いかも。


という事で


Field[] fields = Class.forName("パッケージ名.クラス名").newInstance.getClass().getDeclaredFields;


としてフィールドを取ってこれたので小躍りして喜んだのもつかの間、こんどは↑の方法で生成したオブジェクトに対して動的に生成したメソッドが実行できねぇ。


結論から言うとこうだった。


Class clazz = Class.forName("パッケージ名.クラス名");


//引数無しコンストラクタの場合。引数有りの場合は一旦Constructorで拾ったコンストラクタに対して更にnewInstanceとかいう訳のわから(ry


Object object = clazz.newInstance();


Method method;


method = object.getClass().getMethod("メソッド名", new Class[]{int.class});


Object ret;


//↓とかでも落ちない1.4のクソさに泣かされた


//ret = method.invoke(object.newInstance, new Object[]{ new Integer(1) });


ret = method.invoke(object, new Object[]{ new Integer(1) });


何を理解していればてこずらなかったのか。多分以下の点。


・newInstanceしてなくてもgetClassNameで帰ってくる正しいクラス名に対する疑問


・生成したメソッドが別パッケージのProtectedというオチ


・自称「Java詳しい」という奴の胡散臭さ


あとはXMLの処理という事で使ったDOM関連の知識や基本的なクラス構造に対する知識不足も足を引っ張った。


っつーかオブジェクト指向でなければ実現できない(ってほどでもないけど)ような設計を求められる事がこんなにも辛いとは。








と言う感じで平均睡眠時間が3時間ちょいという状況にも関わらず、全く眠気も無くクソ忙しい日々が今日終わった。


明日(っつーか土曜なんだけど…)からは更に忙しくなりそうなので、すごくワクワクしていますwwwwwwwwwwwwww