实现java闭包的另一种形式
? 记得第一次接触闭包的时候,觉得很奇怪,但从字面上很那理解闭包什么玩意,和闭包有的一比的当属控制反转,真正理解了后觉得就平常了。闭包二字其实是很经典的,闭包代码所表现的东西可不就是一个封闭的、自成一体的功能块吗?简单的说,闭包就是在内部定义的方法,拿到外面去使用。经典的javascript闭包形式如下:
?
function f1(){ var i = 20; function closef(x){ alert(i+x); } return closef } var s = f1(); s(20);
javascript的这种闭包形式的确相当简洁,类似于c语言的函数指针
?众所周知,java实现闭包的形式是内部类,更常用的还是匿名内部类,而这通常还需要定义接口,通过接口的引用来操作内部类对象,从而实现闭包,远没有javascript简洁。这里介绍我在开发中使用的一种java闭包形式,当然还是内部类,我在实现的时候把反射机制加了进来,这么做就是尽量使用起来简单一些。代码如下:
先定义一个接口,接口还是需要的,在以后的闭包使用中,只需要这一个接口。
package p;public interface IMethod {public Object invoke(Object ... objects );}
?
该接口的实现类,这里引入反射:
?
package p;import java.lang.reflect.Method;public class MethodObject implements IMethod {private Object target;//闭包所依赖的对象private String methodName;//闭包方法的名字public MethodObject(){}public MethodObject(Object target, String methodName) {super();this.target = target;this.methodName = methodName;}public Object invoke(Object... objects) {Class clazz = target.getClass();try {Method[] ms = clazz.getDeclaredMethods();Method targetMethod = null;for(Method m : ms){if(methodName.equals(m.getName())){targetMethod = m;break;}}targetMethod.setAccessible(true);return targetMethod.invoke(target, objects);} catch (Exception e) {// TODO Auto-generated catch blockthrow new RuntimeException(e);} }public void rebund(Object anothertarget){target = anothertarget;}}
?
下面是具体使用闭包的形式:
?
public class Person {private int age = 0;public Person(int age) {super();this.age = age;}public IMethod getClosualMethod(){final int i = 10;Object o = new Object(){Date getBirthday(){Calendar c = Calendar.getInstance();c.set(Calendar.YEAR,c.get(Calendar.YEAR) - (age+i));return c.getTime();}};MethodObject mo = new MethodObject(o,"getBirthday");return mo;}}
?
package test;import p.IMethod;public class Test {/** * @param args */public static void main(String[] args)throws Exception {// TODO Auto-generated method stubPerson p = new Person(20);IMethod m = p.getClosualMethod();Object o = m.invoke();System.out.println(o);IMethod m2 = p.getClosualMethod2();m2.invoke("Tom");}}
?
?下面是输出结果:
Sun Jun 03 17:35:05 CST 1979
hello Tom, I am 20 years old
?
从这里可以看到,有了Imethod和MethodObject,在java里使用闭包,就可以像javascript那样方便了。当然,这只是模拟,如果想要达到javascript那样在运行期改变对象的属性和方法,可以在更高一级去模拟。