English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Javaでのデリゲートメカニズムを実現するために反射を使用するコード詳細

要約

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(メール送信時は、#を@に変更してください)で通報し、関連証拠を提供してください。一旦確認がつき、このサイトは即座に侵害を疑われる内容を削除します。

おすすめ