`
aimer311
  • 浏览: 94753 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

反射中如何区分参数是基本类型还是所对应的包装类

    博客分类:
  • java
J# 
阅读更多
package demo.test;

import java.lang.reflect.Method;

/**
 * Java Reflection Cookbook<br/>
 * eg:<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;Reflection r = new Reflection(A.class);<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;Reflection r = new Reflection("com.ehi.A");<br/>
 */
@SuppressWarnings("unchecked")
public class Reflection {

	private Class clazz;

	private Object object;
	
	private Reflection() {

	}

	/**
	 * construct method
	 * @param obj
	 */
	public Reflection(Object obj) {
		this.object = obj;
		clazz = obj.getClass();
	}

	/**
	 * construct method
	 * @param className
	 * @throws Exception
	 */
	public Reflection(String className) throws Exception {
		if (className == null)
			clazz = null;
		else
			clazz = Class.forName(className);
		this.object = clazz.newInstance();
	}
	
	/**
	 * 根据方法名,参数,查找对应的方法,并执行
	 * 
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数
	 * @return 方法返回值
	 * @throws Exception
	 */
	public Object invoke(String methodName, Object[] args)
			throws Exception {
		Class[] parameterTypes = getParameterTypes(args);
		Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
		method.setAccessible(true); 
		return method.invoke(object, args);
	}
	
	private Class[] getParameterTypes(Object[] args) throws Exception {
		if(args == null){
			return null;
		}
		Class[] parameterTypes = new Class[args.length];
		for (int i = 0, j = args.length; i < j; i++) {
			if(args[i] instanceof Integer){
				parameterTypes[i] = Integer.TYPE;
			}else if(args[i] instanceof Byte){
				parameterTypes[i] = Byte.TYPE;
			}else if(args[i] instanceof Short){
				parameterTypes[i] = Short.TYPE;
			}else if(args[i] instanceof Float){
				parameterTypes[i] = Float.TYPE;
			}else if(args[i] instanceof Double){
				parameterTypes[i] = Double.TYPE;
			}else if(args[i] instanceof Character){
				parameterTypes[i] = Character.TYPE;
			}else if(args[i] instanceof Long){
				parameterTypes[i] = Long.TYPE;
			}else if(args[i] instanceof Boolean){
				parameterTypes[i] = Boolean.TYPE;
			}else{
				parameterTypes[i] = args[i].getClass();
			}
		}
		return parameterTypes;
	}
	
	public void print(Integer i){
		System.out.println("Integer: "+i.intValue());
	}
	
	public void print(int i){
		System.out.println("int: "+i);
	}
	
	public static boolean isWrapClass(Class clz) {
        try {
            return ((Class) clz.getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    } 
	
	public static void main(String[] args) throws Exception {
		Reflection r = new Reflection(new Reflection());
		Object[] obj = new Object[1];
		int i = 333;
		obj[0] = i;
                //Integer I = new Integer(333);
                //obj[0] = I;
		r.invoke("print", obj);
	}
}

invoke要实现的是根据方法名和输入的参数自动查找对应的方法,并执行之。遇到的问题就是如何区分Object[]里面存储的是一个基本类型还是其对应的包装类?或者这样的思路根本就是有问题的,请提供下其他的思路。
1
2
分享到:
评论
3 楼 realorg 2008-11-27  
请问 JDK1.4 里能这么做么?
2 楼 aimer311 2008-10-10  
当程序执行到如下时:
int i = 333; 
obj[0] = i; 内存实际上存储的是一个Integer对象。
也就是说当把i存储到数组后就已经是一个Integer的对象了,那么以后就没办法知道它具体是从对象定义而来还是具体类型而来了。
所以我在想除非在传入的参数中必须包含它具体定义类型的信息。
如:
    定义的是int i = 333;那么加上类型信息int.class
    定义的是Integer I = 333,那么加上类型信息Integer.class.
这样是比较麻烦一点。
当调用的函数包含有基本类型的包装类时,那么必须传入参数的具体类型,否则不需要。因为传入包装类的情况比较少,当然也可以判断当传入的是基本类型是必须加上类型信息。根据上面的想法修改后的程序如下:
package demo.test;

import java.lang.reflect.Method;

/**
 * Java Reflection Cookbook<br/>
 * eg:<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;Reflection r = new Reflection(A.class);<br/>
 * &nbsp;&nbsp;&nbsp;&nbsp;Reflection r = new Reflection("com.ehi.A");<br/>
 */
@SuppressWarnings("unchecked")
public class Reflection {

	private Class clazz;

	private Object object;
	
	private Reflection() {

	}

	/**
	 * construct method
	 * @param obj
	 */
	public Reflection(Object obj) {
		this.object = obj;
		clazz = obj.getClass();
	}

	/**
	 * construct method
	 * @param className
	 * @throws Exception
	 */
	public Reflection(String className) throws Exception {
		if (className == null)
			clazz = null;
		else
			clazz = Class.forName(className);
		this.object = clazz.newInstance();
	}
	
	/**
	 * 执行对象方法
	 * 当所执行的函数的参数包含基本类型的包装类是,必须为所有参数定义其参数类型
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数
	 * @param types
	 * 				当函数的参数包含基本类型的包装类时,此参数包含所以参数的类型信息
	 * @return 方法返回值
	 * @throws Exception
	 */
	public Object invoke(String methodName, Object[] args, Class[] types)
			throws Exception {
		Class[] parameterTypes = null;
		if(types == null)
			parameterTypes = getParameterTypes(args);
		else
			parameterTypes = types;
		Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
		method.setAccessible(true); 
		return method.invoke(object, args);
	}
	
	private Class[] getParameterTypes(Object[] args) throws Exception {
		if(args == null){
			return null;
		}
		Class[] parameterTypes = new Class[args.length];
		for (int i = 0, j = args.length; i < j; i++) {
			if(args[i] instanceof Integer){
				parameterTypes[i] = Integer.TYPE;
			}else if(args[i] instanceof Byte){
				parameterTypes[i] = Byte.TYPE;
			}else if(args[i] instanceof Short){
				parameterTypes[i] = Short.TYPE;
			}else if(args[i] instanceof Float){
				parameterTypes[i] = Float.TYPE;
			}else if(args[i] instanceof Double){
				parameterTypes[i] = Double.TYPE;
			}else if(args[i] instanceof Character){
				parameterTypes[i] = Character.TYPE;
			}else if(args[i] instanceof Long){
				parameterTypes[i] = Long.TYPE;
			}else if(args[i] instanceof Boolean){
				parameterTypes[i] = Boolean.TYPE;
			}else{
				parameterTypes[i] = args[i].getClass();
			}
		}
		return parameterTypes;
	}
	
	public void print(Integer i, int j){
		System.out.println("Integer: "+i.intValue());
		System.out.println("int: "+j);
	}
	
	public void print(int i){
		System.out.println("int: "+i);
	}
	
	public static boolean isWrapClass(Class clz) {
        try {
            return ((Class) clz.getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    } 
	
	public static void main(String[] args) throws Exception {
		Reflection r = new Reflection(new Reflection());
		Object[] obj = new Object[2];
		Integer I = new Integer(333);
		obj[0] = I;
		obj[1] = 444;
		Class[] clazz = new Class[2];
		clazz[0] = Integer.class;
		clazz[1] = int.class;
		r.invoke("print", obj, clazz);
	}
}

1 楼 aimer311 2008-10-09  
按照以上的程序并不能调用print(Integer i).当然,我知道通过
Method method = clazz.getDeclaredMethod("print", int.class);
Method method = clazz.getDeclaredMethod("print", Integer.class);可以区分这两个函数,这样相当于实现知道参数类型。而如果从所输入的参数来判断是什么类型,再判断调用哪个函数就不清楚了。如:
当obj[0] = 333,表明此时的参数是int型,那么调用的应该是print(int i);
当obj[0] = new Integer(333),表明此时的参数是Integer型,那么调用的应该是print(Integer i);


相关推荐

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    17.7.3 简化语法3:局部变量不需要手动包装到类中即可传给回调方法 17.8 委托和反射 第18章 定制attribute 18.1 使用定制attribute 18.2 定义自己的attribute类 18.3 attribute的构造器和字段/属性的数据类型 ...

    Java基础知识点.html

    类加载器 ClassLoader 反射 Stream 流 函数式编程 Lambda 表达式 网络编程-协议 网络编程-端口 网络编程-IP 多线程 IO流-字节流 IO流-字符流 IO流-转换流 File Map HashMap 序列化和反序列化 可变参数 类型通配符 ...

    CLR.via.C#.(中文第3版)(自制详细书签)

    17.7.3 简化语法3:局部变量不需要手动包装到类中即可传给回调方法 17.8 委托和反射 第18章 定制attribute 18.1 使用定制attribute 18.2 定义自己的attribute类 18.3 attribute的构造器和字段/属性的数据类型 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    17.7.3 简化语法3:局部变量不需要手动包装到类中即可传给回调方法 17.8 委托和反射 第18章 定制attribute 18.1 使用定制attribute 18.2 定义自己的attribute类 18.3 attribute的构造器和字段/属性的数据类型 ...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    17.7.3 简化语法3:局部变量不需要手动包装到类中即可传给回调方法 17.8 委托和反射 第18章 定制attribute 18.1 使用定制attribute 18.2 定义自己的attribute类 18.3 attribute的构造器和字段/属性的数据类型 ...

    疯狂JAVA讲义

    6.1 基本数据类型的包装类 167 6.2 处理对象 170 6.2.1 打印对象和toString方法 170 6.2.2 ==和equals比较运算符 172 6.3 类成员 175 6.3.1 理解类成员 175 6.3.2 单例(Singleton)类 176 6.4 final修饰符 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     25.2 在业务代理类中访问EJB组件  25.3 发布J2EE应用  25.3.1 在JBoss上部署EJB组件  25.3.2 在JBoss上部署Web应用  25.3.3 在JBoss上部署J2EE应用  25.4 小结 附录A 标准SQL语言的用法  A.1 数据...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     25.2 在业务代理类中访问EJB组件  25.3 发布J2EE应用  25.3.1 在JBoss上部署EJB组件  25.3.2 在JBoss上部署Web应用  25.3.3 在JBoss上部署J2EE应用  25.4 小结 附录A 标准SQL语言的用法  A.1 数据...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     25.2 在业务代理类中访问EJB组件  25.3 发布J2EE应用  25.3.1 在JBoss上部署EJB组件  25.3.2 在JBoss上部署Web应用  25.3.3 在JBoss上部署J2EE应用  25.4 小结 附录A 标准SQL语言的用法  A.1 数据...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     25.2 在业务代理类中访问EJB组件  25.3 发布J2EE应用  25.3.1 在JBoss上部署EJB组件  25.3.2 在JBoss上部署Web应用  25.3.3 在JBoss上部署J2EE应用  25.4 小结 附录A 标准SQL语言的用法  A.1 数据...

    C#5.0本质论第四版(因文件较大传的是百度网盘地址)

    16.5.8 在单个类中创建多个迭代器 469 16.5.9 yield语句的要求 470 16.6 小结 470 第17章 反射、特性和动态编程 471 17.1 反射 471 17.1.1 使用System.Type访问元数据 472 17.1.2 成员调用...

    aspnet公共类cs文件.rar

    供Asp.Net直接调用的包装类(WebPreview.cs) 计算机重启、关电源、注销、关闭显示器辅助类(WindowsExitHelper.cs) ----------NONONONO-------------- 全局统一的缓存类(Cache.cs) 常用显示日期时间、农历、生肖的...

    面向对象技术与UML课件及源代码-by 南邮-陈杨

    10.4基本数据类型的包装类 10.4.1认识包装类 10.4.2通过包装类进行数据转换 10.5认识Java集合 10.5.1为什么需要集合 10.5.2Java中的集合 10.6使用一维集合 10.6.1认识一维集合 10.6.2使用List集合 10.6.3...

    apache-commons源码及jar文件

    Commons-BeanUtils 提供对 Java 反射和自省API的包装 Betwixt Betwixt提供将 JavaBean 映射至 XML 文档,以及相反映射的服务. Chain Chain 提供实现组织复杂的处理流程的“责任链模式”. CLI CLI 提供针对命令行...

    Java开发技术大全 电子版

    7.3.2OutputStreamWriter类中的方法250 7.3.3从键盘输入250 7.3.4文件复制251 7.4文件属性处理252 7.4.1File类中的方法252 7.4.2File类使用示例——文件列表253 7.5随机访问文件254 7.5.1RandomAccessFile类...

    java基础案例与开发详解案例源码全

    3.2.1 Java中的八种基本数据类型34 3.2.2 普及二进制36 3.2.3 进制间转换37 3.2.4 基本数据类型间转换38 3.2.5 数据类型应用实例38 3.2.6 引用数据类型39 3.3 关键字.标识符.常量39 3.3.1 变量命名规范39 3.3.2 ...

    DotNet公用类(超多附文档)

    22.供Asp.Net直接调用的包装类(WebPreview.cs) 23.计算机重启、关电源、注销、关闭显示器辅助类(WindowsExitHelper.cs) ----------NONONONO-------------- 1.全局统一的缓存类(Cache.cs) 2.常用显示日期时间、农历...

Global site tag (gtag.js) - Google Analytics