クラスから別の場所のクラスを呼び出す構造を作りたくて、ClassLoaderを勉強しています。
まず、ClassLoaderを継承したLoaderを作成しなくてはいけないというのがわかり、その中で抽象メソッドloadClassと、関係するdefine,resolve,findSystemなどを記述してやるらしいというのまでは、あやふやながら理解できました。
それで、呼び出す側では、Loader.loadClassを呼んでクラスをロードし、newInstanceメソッドを呼べば、その実体ができる"らしい"まで解読して頭がパンクしてしまいました。
疑問は、以下の通りです。
・「Loaderは自分で作らないといけない」とあったのですが、ClassLoaderを継承させたLoaderを自前で書かないといけないのでしょうか。単にオブジェクトを生成するだけでいいんでしょうか。簡単なサンプルがあれば嬉しいのですが・・・。
・ ひとまず、簡単な計算を行うクラスを作って呼び出してみたいのですが、newInstanceを実行するとインスタンスが生成されて即中身が実行される、という説明文を読んだのですが、値の受け渡しはどうすればできるのでしょうか。
以上、よろしくご教示お願いいたします。
No.1ベストアンサー
- 回答日時:
大抵は URLClassLoader をインスタンス化するだけで用が足ると思います。
たとえば C:/classes からクラスを読込むのであれば、
URLClassLoader loader =
new URLClassLoader( new URL[ ]{ new File("c:/classes").toURL() } );
でロードするクラスを完全限定名で指定して、
Class clazz = Class.forName("sample.Hoge", true, loader);
そしてインスタンス化。
Object obj = clazz.newInstance();
ただここからが問題で、
このオブジェクトは sample.Hoge 型に
キャストできません。
このオブジェクト特有のメソッドを実行したいのなら、
リフレクションを使います。
Method method =
clazz.getMethod( "メソッド名", new Class[0] ); // 引数なし
method.invoke( obj, new Object[0] );
コメントありがとうございます。ClassLoaderが直接生成できないワケがどうしてもわからなかったので、URLClassLoaderでサンプルを作成してみました。結果は上手くいったのですが、ここで作ったオブジェクト(中身はロードしたクラスの実体、でいいんでしょうか)の触り方がいまいちわからないんです。生成した瞬間にクラスが実行されるようですが、呼び出し元とは関係ない空間で動いているのでしょうか。
リフレクションというのがあるらしい、は分かるのですが、いまいちパッとしなくて・・・すみません;
(method.invokeで引数を渡して、同時に戻ったオブジェクトを取り出せるのでしょうか)
No.3
- 回答日時:
1コ前の者です。
投稿した後に気づいたのですが、「多くの場合は問題になりません」はウソで、けっこう引っかかりやすい部分だと思ったので補足を。
public class Main {
public static void main(String[] args) {
ClassLoader loader = new MyClassLoader();
Class clazz = Class.forName("hoge.Hoge", true, loader);
HogeInterface hoge = (HogeInterface)clazz.newInstance();
hoge.start();
}
}
この例の場合、Mainクラス(のクラスローダ)はhoge.Hogeクラスを知らないので、hoge.Hogeにキャストすることはできません。(もし起動クラスパスにhoge.Hogeがあったとしても、MyClassLoaderがロードすれば別のクラスになります)
このような場合、Mainクラスが知っているクラスなりインタフェースにキャストしてやるようにすると良いと思います。hoge.HogeはHogeInterfaceをimplementsする。
もちろん、#1の方の回答のようにリフレクション経由でのメソッド呼び出しも可能です。
Hogeクラスやその中の呼び出しではクラスローダがMyClassLoaderなので、いくらでもHogeクラスを使用することができます。
あれからちょっと考えまして、リフレクションでメソッドを呼んだり試行錯誤して、少しずつわかってきました。
ひとまず簡単なものを書いてみて、参照ができるということが確認できましたので、徐々に理解を深めてみようと思います。ありがとうございました。
No.2
- 回答日時:
以下、私の理解の範囲で。
・自前クラスローダからロードした場合であっても、Class#newInstanceで作ったオブジェクトをキャストすることはできます。
ただし、他でシステムクラスローダがhoge.Hogeをロードした場合、自前クラスローダのhoge.Hogeクラスとは同じ名前の別のクラスになります。(キャストしたときにはClassCastExceptionが発生する)
しかし、クラスのロードには、その参照元クラスのクラスローダが使われますので、多くの場合は問題になりません。
class Hoge {
static Hige hige;
}
となっていた場合、HigeクラスのロードはHogeをロードしたクラスローダが行います。
・クラスロードの処理に何かを噛ませることが目的でしたら、URLClassLoaderを継承することができます。
また、そもそもURLで表せないものからクラスをロードしたい場合は、ClassLoaderを継承するのが良いと思います。
一度ロードしたクラスのキャッシュ処理などはClassLoaderの中にありますので、自前クラスローダはfindClassをオーバーライドするだけで済みます。
(リソースのロードにも対応するためには、他にも実装が必要になりますが)
・Class#newInstanceは引数なしのコンストラクタを呼びます。引数を渡したい場合には、java.lang.reflect.Constructorを使います。
ありがとうございます。クラスローダを自前で作る理由というのがわからなかったので、URLClassLoaderを生成してみました。
ロードしたクラスに引数を渡せるというのはなんとなく理解できたのですが、具体的な方法(必死にリファレンスを読んではいるのですが、サンプルが少なくて・・・)やロードしたクラスから呼び出し元と同じ場所に配置してあるクラスを呼べるのかといったことが結局まだわからないので・・・もっと勉強してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java java 次の機能を有するメソッドを自クラスに作成し、実装したいです。 機能 名前判定機能 →名前が 3 2022/06/16 16:08
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/17 18:41
- その他(プログラミング・Web制作) Pythonで複数のメソッドをまとめて管理する方法について 1 2023/03/30 00:01
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/06 09:28
- JavaScript [Java] Edgeでのアドレスバー非表示について 3 2022/04/20 17:51
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- その他(データベース) pythonでsqlight勉強中、クエリー結果の利用法教えて下さい 1 2022/04/28 20:38
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「天声人語」をインターネット...
-
自作のクラスファイルがインポ...
-
配列の重複する値とその個数を...
-
javaのコンパイルができません...
-
グローバルIPとプライベートIP...
-
河合塾のクラス分けについて
-
eclipseのパッケージって何?
-
同一パッケージにあるクラスが...
-
1 つのヘッダファイルに複数の...
-
main()を持つクラスが2つ以上...
-
成人式の後中3のクラスで集まろ...
-
クラス見てから 女の子5人 ネタ...
-
内部クラス?のエラー
-
IPアドレスの3バイト目の呼び方
-
どこからも呼ばれていない無意...
-
skeletonのクラスって何?
-
命名規約は連番でいいのか?
-
Javaのscannerクラスの問題なの...
-
標準入力 System.in について
-
中学生 発表を面白くするには
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
3年間同じクラスになる確率
-
「天声人語」をインターネット...
-
配列の重複する値とその個数を...
-
自分事ですが、私のLINEのスク...
-
java eclipse 型に解決できません
-
同じクラスにならない確率を教...
-
どこからも呼ばれていない無意...
-
グローバルIPとプライベートIP...
-
担任にプレゼント
-
数学の計算問題。 3年間同じク...
-
クラスのプロパティに構造体を...
-
河合塾のクラス分けについて
-
IPアドレスのクラスAを取得して...
-
共通で使う関数を集めたクラス...
-
自作のクラスファイルがインポ...
-
1 つのヘッダファイルに複数の...
-
ヒートテックやファイバーヒー...
-
dllと同じプロジェクトにする方法
-
main()を持つクラスが2つ以上...
-
同一パッケージにあるクラスが...
おすすめ情報