论坛首页 Java企业应用论坛

实现java闭包的另一种形式

浏览 3176 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (4) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-06-03  

  记得第一次接触闭包的时候,觉得很奇怪,但从字面上很那理解闭包什么玩意,和闭包有的一比的当属控制反转,真正理解了后觉得就平常了。闭包二字其实是很经典的,闭包代码所表现的东西可不就是一个封闭的、自成一体的功能块吗?简单的说,闭包就是在内部定义的方法,拿到外面去使用。经典的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 block
			throw 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 stub
		Person 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那样在运行期改变对象的属性和方法,可以在更高一级去模拟。

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics