English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
要約
Javaに既存のデリゲートメカニズムがないことにずっと懸念していましたが、幸いにも最近少し時間がありましたので、反射を使って簡単なデリゲートモジュールを作成しました。
モジュールAPI
public Class Delegater()//空のコンストラクタ、このクラスはデリゲートインスタンスを管理し、デリゲートメソッドを実現します //静的メソッドデリゲートを追加し、该方法とパラメータが構成するインスタンスを表す整型値IDを返します。失敗した場合、返り値は-1。 public synchronized int addFunctionDelegate(Class<?> srcClass,String methodName,Object... params); //インスタンスメソッドデリゲートを追加し、该方法とパラメータが構成するインスタンスを表す整型値IDを返します。失敗した場合、返り値は-1。 public synchronized int addFunctionDelegate(Object srcObj,String methodName,Object... params); //整型IDに基づいてデリゲートインスタンスからメソッドデリゲートを削除し、成功したかどうかを返します public synchronized Boolean removeMethod(int registerID); //このデリゲートインスタンス内のすべてのメソッドデリゲート(無序)を順次実行します public synchronized void invokeAllMethod(); //パラメータテーブルをパラメータタイプテーブルに変換します private Class<?>[] getParamTypes(Object[] params); //指定されたClass、メソッド名、パラメータタイプテーブルからメソッドインスタンスを取得します private Method getDstMethod(Class<?> srcClass, String methodName, Class<?>[] paramTypes); class DelegateNode(Method refMethod,Object[] params)//DelegateNodeクラスはObjectを使用して構築されない場合、静的メソッドデリゲートを記述しており、メソッドインスタンス及びパラメータテーブルを含んでいます class DelegateNode(Object srcObj,Method refMethod,Object[] params)//DelegateNodeクラスはObjectを使用して構築される場合、インスタンスメソッドデリゲートを記述しており、クラスインスタンス、メソッドインスタンス及びパラメータテーブルを含んでいます public void invokeMethod(); //このノードの記述されたメソッドデリゲートを実行します
ソースコード
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Hashtable; /**DelegaterクラスはRTTIおよび反射を使用してJavaのデリゲートメカニズムを実現しています * @author 三向板砖 * */ public class Delegater { static int register = Integer.MIN_VALUE; //ID割り当て変数 Hashtable<Integer,DelegateNode> nodeTable; //IDと対応するデリゲートの管理コンテナ public Delegater() { nodeTable = new Hashtable<Integer,DelegateNode>(); } //静的メソッドデリゲートを追加します public synchronized int addFunctionDelegate(Class<?> srcClass,String methodName,Object... params) { Class<?>[] paramTypes = getParamTypes(params); Method refMethod; if((refMethod = getDstMethod(srcClass,methodName,paramTypes)) != null) { register++; nodeTable.put(register,new DelegateNode(refMethod, params)); return register; } else { return -1; } } //動的メソッドデリゲートを追加します public synchronized int addFunctionDelegate(Object srcObj,String methodName,Object... params) { Class<?>[] paramTypes = getParamTypes(params); Method refMethod; if((refMethod = getDstMethod(srcObj.getClass(),methodName,paramTypes)) != null) { register++; nodeTable.put(register,new DelegateNode(srcObj,refMethod, params)); return register; } else { return -1; } } //メソッドデリゲートを削除します public synchronized Boolean removeMethod(int registerID) { if(nodeTable.containsKey(registerID)) { nodeTable.remove(registerID); return true; } return false; } //無序にデリゲートメソッドを実行します public synchronized void invokeAllMethod() { for (DelegateNode node:nodeTable.values()) { node.invokeMethod(); } } //パラメータテーブルをパラメータタイプテーブルに変換します private Class<?();> getParamTypes(Object[] params) { Class<?>[] paramTypes = new Class<?>[params.length]; for (int i = 0; i < params.length; i++) { paramTypes[i] = params[i].getClass(); } return paramTypes; } //Classクラスのインスタンス、メソッド名、パラメータタイプテーブルからMethodインスタンスを取得します private Method getDstMethod(Class<?> srcClass, String methodName, Class<?>[] paramTypes) { Method result = null; try { result = srcClass.getMethod(methodName, paramTypes); if(result.getReturnType() != void.class) { System.out.println("警告、メソッド:"+methodName+" はリターン値を持っています!); } } catch (NoSuchMethodException | SecurityException e) { System.out.println("メソッドが見つかりません:"+methodName+"、確認して、存在し、表示されていることを!); } return result; } } class DelegateNode { Object srcObj; Method refMethod; Object[] params; public DelegateNode(Method refMethod, Object[] params) { this.refMethod = refMethod; this.params = params; } public DelegateNode(Object srcObj, Method refMethod, Object[] params) { this.srcObj = srcObj; this.refMethod = refMethod; this.params = params; } public void invokeMethod() { try { refMethod.invoke(srcObj,params); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { System.out.println("メソッド:")+refMethod.toString()+"呼び出し失敗!"); } } }
モジュールテスト
public class DelegaterTest { public void showInfo() { System.out.println("Hello Delegate!"); } public void showCustomInfo(String info) { System.out.println(info); } public static void showStaticInfo() { System.out.println("Static Delegate!"); } public static void showCustomStaticInfo(String info) { System.out.println(info); } public static void main(String[] args) { Delegater dele = new Delegater(); DelegaterTest tester = new DelegaterTest(); int ID = dele.addFunctionDelegate(tester,"showInfo"); dele.addFunctionDelegate(tester,"showCustomInfo","Custom!"); dele.addFunctionDelegate(DelegaterTest.class,"showStaticInfo"); dele.addFunctionDelegate(DelegaterTest.class,"showCustomStaticInfo","StaticCustom!"); dele.invokeAllMethod(); dele.removeMethod(ID); System.out.println("------------------"); dele.invokeAllMethod(); } }
実行結果:
StaticCustom!
StaticDelegate!
Custom!
HelloDelegate!
------------------
StaticCustom!
StaticDelegate!
Custom!
その他の事項
一部のpublicメソッドはsynchronizedを使用して、register変数のスレッドセーフを保証し、多线程によってエラーが発生しないようにしています。
返り値を持つデリゲートに対して警告が表示されますが、モジュールはそのデリゲートを受け入れます。ただし、デリゲートを実行する際には返り値を受け取ることができません。
追加できるデリゲートの最大値はInteger.MAX_VALUEです-Integer.MIN_VALUEを超えたエラーハンドリングは考慮されていません(もっとも、デリゲートが必要な関数はこれほど多くはないでしょう。)
デリゲートの実行は無秩序で、パフォーマンスが必要な場合、デリゲートの関数にはブロッキングプロセスを持たない方が良いです。それがあれば、他のデリゲート関数の実行に影響を与えます。
何かご不明な点があれば、共有して一緒に議論してください。
まとめ
これで、Javaでのリフレクトを通じてデリゲートメカニズムを実現するための全ての内容が終わりました。皆様の助けになれば幸いです。興味がある方は、このサイトの他のJava関連の特集もご覧ください。不十分な点があれば、コメントを残してください。皆様のサポートに感謝します!
声明:この記事の内容はインターネットから収集され、著作権者が所有しており、インターネットユーザーによって自発的に提供されたものであり、このサイトは所有権を持ちません。また、人間のエディタが編集していないため、著作権に関する責任を負いません。著作権に関する問題があれば、メールを送信してください:notice#oldtoolbag.com(メール送信時は、#を@に変更してください)で通報し、関連証拠を提供してください。一旦確認がつき、このサイトは即座に侵害を疑われる内容を削除します。