通过反射实现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("Warning,Method:"+methodName+" has a return value!");
			}
		}
		catch (NoSuchMethodException | SecurityException e) {
			System.out.println("Can Not Found Method:"+methodName+",ensure it's exist and visible!");
		}
		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("Method:"+refMethod.toString()+" invoke fail!");
		}
	}
}

模块测试

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相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • 详谈Java编程之委托代理回调、内部类以及匿名内部类回调(闭包回调)

    最近一直在看Java的相关东西,因为我们在iOS开发是,无论是Objective-C还是Swift中,经常会用到委托代理回调,以及Block回调或者说是闭包回调.接下来我们就来看看Java语言中是如何实现委托代理回调以及闭包回调的.当然这两个技术点虽然实现起来并不困难,但是,这回调在封装一些公用组件时还是特别有用的.所以今天,还是有必要把Java中的委托代理回调以及闭包回调来单独的拿出来聊一下. 本篇博客我们依然依托于实例,先聊聊委托代理回调的实现和使用场景,然后再聊一下使用匿名内部类来进行回调

  • C#匿名委托和Java匿名局部内部类使用方法示例

    测试代码 复制代码 代码如下: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; namespace CSharpStudy{    class Program    {        static void Main(string[] args)        {            int i = 0; Action

  • Java方法反射实现原理详解

    博主说:Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制.在本文中,占小狼分析了 Java 反射机制的实现原理(源码),感兴趣的同学可以通过阅读本文花上几分钟了解了解. 正文 方法反射实例 public class ReflectCase { public static void main(String[] args) throws Exce

  • Java 基础详解(泛型、集合、IO、反射)

    计划把 Java 基础的有些部分再次看一遍,巩固一下,下面以及以后就会分享自己再次学习的一点笔记!不是有关标题的所有知识点,只是自己觉得模糊的一些知识点. 1.对于泛型类而言,你若没有指明其类型,默认为Object: 2.在继承泛型类以及接口的时候可以指明泛型的类型,也可以不指明: 3.泛型也数据库中的应用: 写一个 DAO 类对数据库中的数据进行增删改查其类型声明为 <T> .每张表对应一个类,对应每一张表实现一个类继承该 DAO 类并指明 DAO 泛型为该数据表对应的类,再实现一个与该表匹

  • java实现事件委托模式的实例详解

    java实现事件委托模式的实例详解 举例说明: 一个班级,有两类学生,A类:不学习,玩,但是玩的东西不一样,有的是做游戏,与的是看电视(有点不合理) B类:放哨的学生,专门看老师的动向,如果老师进班了就立即通知大家. 如此就形成了一个需求,放哨的学生要通知所有玩的学生:老师来了,而不同的学生有不同的反应,有的马上把电视关闭,有的停止玩游戏. 设计的要求如下,让A类学生和B类学生完全解耦,即A类完全不知道B类的学生,却可以通知B类的学生. 代码及说明如下: Event 类,定义了一个事件类: pa

  • Java反射简易教程

    关于Java反射,我们需要弄懂以下几个问题: 反射是什么?反射有什么用?怎么用反射? 下面我们来一一进行讲解: 一.反射是什么? Reflection的意思是"反射.映象.倒影",用在Java身上指的是我们可以于运行时加载.探知.使用编译期间完全未知的classes.换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体.或对其fields设值.或唤起其methods. Java反射机制是在运行状态中,对于任意一个

  • Java 反射机制的实例详解

    Java 反射机制的实例详解 前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 用一句话总结就是反射可以实现在运行时可以知道任意一个类的属性和方法. 反射

  • 解析Java虚拟机中类的初始化及加载器的父委托机制

    类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有经过显式初始化的静态变量将原有的值. 一个比较奇怪的例子: package com.mengdd.classloader; class Singleton { // private static Singleton mInstance = new Singleton();// 位置1 // 位置1输

  • Java反射机制实例代码分享

    本文旨在对Java反射机制有一个全面的介绍,希望通过本文,大家会对Java反射的相关内容有一个全面的了解. 阅读本文之前,大家可先行参阅<重新理解Java泛型>. 前言 Java反射机制是一个非常强大的功能,在很多大型项目比如Spring, Mybatis都可以看见反射的身影.通过反射机制我们可以在运行期间获取对象的类型信息,利用这一特性我们可以实现工厂模式和代理模式等设计模式,同时也可以解决Java泛型擦除等令人苦恼的问题.本文我们就从实际应用的角度出发,来应用一下Java的反射机制. 反射

  • 通过反射实现Java下的委托机制代码详解

    简述 一直对Java没有现成的委托机制耿耿于怀,所幸最近有点时间,用反射写了一个简单的委托模块,以供参考. 模块API public Class Delegater()//空参构造,该类管理委托实例并实现委托方法 //添加一个静态方法委托,返回整型值ID代表该方法与参数构成的实例.若失败,则返回-1. public synchronized int addFunctionDelegate(Class<?> srcClass,String methodName,Object... params)

  • Java多线程之线程通信生产者消费者模式及等待唤醒机制代码详解

    前言 前面的例子都是多个线程在做相同的操作,比如4个线程都对共享数据做tickets–操作.大多情况下,程序中需要不同的线程做不同的事,比如一个线程对共享变量做tickets++操作,另一个线程对共享变量做tickets–操作,这就是大名鼎鼎的生产者和消费者模式. 正文 一,生产者-消费者模式也是多线程 生产者和消费者模式也是多线程的范例.所以其编程需要遵循多线程的规矩. 首先,既然是多线程,就必然要使用同步.上回说到,synchronized关键字在修饰函数的时候,使用的是"this"

  • Java垃圾回收机制算法详解

    概述 Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对JVM中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息的保证JVM中的内存空间,防止出现内存泄露和溢出问题. 在真实工作中的项目中,时不时的会发生内存溢

  • Java的SPI机制实例详解

    Java的SPI机制实例详解 SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoader的文档里有比较详细的介绍.究其思想,其实是和"Callback"差不多."Callback"的思想是在我们调用API的时候,我们可以自己写一段逻辑代码,传入到API里面,API内部在合适的时候会调用它,从而实现某种程度的"定制". 典型的是Colle

  • java实现队列数据结构代码详解

    什么是队列结构 一种线性结构,具有特殊的运算法则[只能在一端(队头)删除,在另一端(队尾)插入]. 分类: 顺序队列结构 链式队列结构 基本操作: 入队列 出队列 给出一些应用队列的场景 1):当作业被送到打印机的时候,就可以按到达的顺序排起来,因此每一份作业是队列的节点. 2):售票口的人买票的顺序的按照先来先买的顺序售票. 3):当所有的终端被占用,由于资源有限,来访请求需要放在一个队列中等候. 队列是先进先出的! 我们设置一个叫做LinkQueue<T>的泛型集合类,该类里面有 Node

  • java内部测试类代码详解

    我们一般使用的java内部类有4种形式:一般内部类.局部内部类.匿名内部类.静态内部类.以下是我作的一个测试,以说明各种内部类的特性. 有关内部类的特性,代码中有详细说明,如下. /* * java内部类测试 * * InterObj反射结果: * * private int i * private InterObj$InterA ia * public InterObj() * public static void main(java.lang.String[]) * private int

  • Java编程复用类代码详解

    本文研究的主要是Java编程中的复用类,那么到底复用类是什么东西,又有什么用法,下面具体介绍. 看了老罗罗升阳的专访,情不自禁地佩服,很年轻,我之前以为和罗永浩一个级别的年龄,也是见过的不是初高中编程的一位大牛之一,专访之后,发现老罗也是一步一个脚印的人.别说什么难做,做不了,你根本就没去尝试,也没有去坚持. If you can't fly then run,if you can't run then walk, if you can't walk then crawl,but whateve

  • 一个通用的Java分页基类代码详解

    分页的基类 import java.util.List; /** * 分页显示的标准类,基本操作,是先给予-当前页数一共的数据条数-每页显示的条数, * 然后在初始化该类,得到总共页数,和开始序号和结束序号, * 然后数据库分页用到开始序号和结束序号,得到数据集合后赋值给该类的list属性, * * 然后把该类发送到jsp页面,进行访问 * @author admin * * @param <T> */ public class PageBean<T> { private int

  • Java中可变长度参数代码详解

    到J2SE1.4为止,一直无法在Java程序里定义实参个数可变的方法--因为Java要求实参(Arguments)和形参(Parameters)的数量和类型都必须逐一匹配,而形参的数目是在定义方法时就已经固定下来了.尽管可以通过重载机制,为同一个方法提供带有不同数量的形参的版本,但是这仍然不能达到让实参数量任意变化的目的. 然而,有些方法的语义要求它们必须能接受个数可变的实参--例如著名的main方法,就需要能接受所有的命令行参数为实参,而命令行参数的数目,事先根本无法确定下来. 对于这个问题,

  • Java实现搜索功能代码详解

    首先,我们要清楚搜索框中根据关键字进行条件搜索发送的是Get请求,并且是向当前页面发送Get请求 //示例代码 请求路径为当前页面路径 "/product" <!-- 搜索框 get请求 根据商品名称的关键字进行搜索--> <form action="/product" class="form-inline pull-left" > <input type="text" name="pr

随机推荐