Frequently used reflection utils

在分享导出导入csv格式的文件之前,个人觉着先了解下什么是反射以及将要用到的反射工具;

The name reflection is used to describe code which is able to inspect other code in the same system (or itself).

For example, say you have an object of an unknown type in Java, and you would like to call a 'doSomething' method on it if one exists. Java's static typing system isn't really designed to support this unless the object conforms to a known interface, but using reflection, your code can look at the object and find out if it has a method called 'doSomething' and then call it if you want to.

So, to give you a code example of this in Java (imagine the object in question is foo) :

 

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

以上来自:https://stackoverflow.com/questions/37628/what-is-reflection-and-why-is-it-useful 就很好的说明了问题,就不再赘述.

前人种树,后人纳凉,感谢@author calvin ;

硬上:

 private static final String SETTER_PREFIX = "set";

 private static final String GETTER_PREFIX = "get";

 

/**
     * 调用Getter方法. 支持多级,如:对象名.对象名.方法
     */
    public static Object invokeGetter(Object obj, String propertyName) {
	Object object = obj;
	for (String name : StringUtils.split(propertyName, ".")) {
	    String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
	    object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
	}
	return object;
    }

 

   /**
     * 直接调用对象方法, 无视private/protected修饰符.
     * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. 同时匹配方法名+参数类型,
     */
    public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes, final Object[] args) {
	Method method = getAccessibleMethod(obj, methodName, parameterTypes);
	if (method == null) {
	    throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
	}

	try {
	    return method.invoke(obj, args);
	} catch (Exception e) {
	    throw convertReflectionExceptionToUnchecked(e);
	}
    }
    /**
     * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null.
     * 匹配函数名+参数类型。
     * 
     * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object...
     * args)
     */
    public static Method getAccessibleMethod(final Object obj, final String methodName, final Class<?>... parameterTypes) {
	Validate.notNull(obj, "object can't be null");
	Validate.notBlank(methodName, "methodName can't be blank");

	for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
	    try {
		Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
		makeAccessible(method);
		return method;
	    } catch (NoSuchMethodException e) {
		// Method不在当前类定义,继续向上转型
		continue;// new add
	    }
	}
	return null;
    }
/**
     * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
     */
    public static void makeAccessible(Method method) {
	if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
	    method.setAccessible(true);
	}
    }
 /**
     * 调用Setter方法, 仅匹配方法名。 支持多级,如:对象名.对象名.方法
     */
    public static void invokeSetter(Object obj, String propertyName, Object value) {
	Object object = obj;
	String[] names = StringUtils.split(propertyName, ".");
	for (int i = 0; i < names.length; i++) {
	    if (i < names.length - 1) {
		String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
		object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
	    } else {
		String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
		invokeMethodByName(object, setterMethodName, new Object[] { value });
	    }
	}
    }
    /**
     * 直接调用对象方法, 无视private/protected修饰符,
     * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
     * 只匹配函数名,如果有多个同名函数调用第一个。
     */
    public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
	Method method = getAccessibleMethodByName(obj, methodName);
	if (method == null) {
	    throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
	}

	try {
	    return method.invoke(obj, args);
	} catch (Exception e) {
	    throw convertReflectionExceptionToUnchecked(e);
	}
    }

 

 

在这里要说明的是:由于反射是要消耗性能的,如果某一方法反复被调用,最好加入缓存,主题在导入数据时,某一类的某一属性setter/getter方法被频繁调用,就要加入缓存.缓存框架机制有很多,以后单独陈述,在这里推荐轻量级的google guava,亦可用Map.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值