java 反射中的包装类与基本数据类型

写了个执行反射方法的函数,但是却老出问题,捣鼓了下,原来是基本数据类型出了问题,

调用反射中的方法时,需要知道方法的参数类型,

Method getDeclaredMethod(String name, Class<?>... parameterTypes)

但是因为参数是可变类型,我们要单独下一个执行反射类中方法的工具方法的时候,要用数组来处理,就会出现自动装箱问题,

比如我定义的函数test1(int i,String s),我要调用这个方法,invoke(obj,"test1",1,"hello"),程序自动将int类型的1包装成Integer类型的1,就会出现找不到此方法的异常,

解决办法

  • 1写方法的时候将int写成Integer类型,建议
  • 2需要将其转换成基本包装类型的Class

包装类的定义下都有一个属性TYPE,根据这个属性有还是没有,可以判断出装箱后的Class是否为包装类的Class,

执行一个函数的前提是你知道它的参数类型是基本的还是包装的,如果有包装类型的参数,那就不需要处理,自动装箱后变成包装类的Class,如果参数中没有包装类,是引用类和基本数据类型,就需要将自动包装的Class转换为基本类型的Class,

下面的transferToPrime函数就起这个作用,(说明,如果是单独的一条语句Method method=c.getDeclaredMethod(String name, Class<?>... parameterTypes),你就可以手动地写成int.class,double.class,但是抽取成方法时,需要注意

//如果参数中有包装类,将其转换为基本类型,其他类型不变
	public Class transferToPrime(Class c, String fieldName) {

		Field[] fields = c.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {

			if (fields[i].getName().equals(fieldName)) {
				try {

					return (Class) fields[i].get(null);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return c;

	}
	//执行方法
	public Object invoke(Object obj, String methodName, Object... args) {
		Class[] params = new Class[args.length];
		for (int i = 0; i < args.length; i++) {

			Class f = args[i].getClass();
			params[i] = f;
//			params[i] = transferToPrime(f, "TYPE");
			System.out.println(params[i]);
		}

		try {
			// 从父类和子类所有方法中找
			Method m = obj.getClass().getMethod(methodName, params);
			return m.invoke(obj, args);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	//执行方法
	public Object invoke(String className, String methodName, Object... args) {
		Object obj = null;
		try {

			obj = Class.forName(className).getDeclaredConstructor().newInstance();

			return invoke(obj, methodName, args);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

另外,jdk9只有已经把Class类的newInstance方法废弃,虽然还可以用,推荐使用Class的getDeclaredConstructor的newInstance方法,调用类中的无参构造器来创建对象,这也就是无参构造器存在的意义啦.

循环获取指定字段包括父类的,如果没有报异常:

public Field getField(Class clazz,String fieldName){
		Field field = null;
		for(Class clazz2 = clazz;clazz2 != Object.class;
				clazz2=clazz2.getSuperclass()){
			try {
				field = clazz2.getDeclaredField(fieldName);
			} catch (Exception e) {	}
		}
		return field;
	}

循环获取方法,包括父类的,如果没有,报错

/**
	 * 循环遍历当前类及父类的所有方法,寻找指定方法
	 * @param c要获取的Class对象
	 * @param methodName方法名
	 * @param parameterTypesClass类型的可变参数
	 * @return
	 */
	public Method getMethod(Class c, String method, Class... parameterTypes) {
		for (; c != Object.class; c = c.getSuperclass()) {
			try {
				Method m = c.getDeclaredMethod(method, parameterTypes);
				return m;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

猜你喜欢

转载自blog.csdn.net/sinat_41132860/article/details/84574064