`
暗黑小菠萝
  • 浏览: 46824 次
  • 性别: Icon_minigender_2
  • 来自: 大连
社区版块
存档分类
最新评论

Java反射机制与实例

    博客分类:
  • Java
阅读更多
java的反射机制其实更多用于一些框架中,实际的项目中比较少的能用到。
最近要实现一个小的功能就是将前端返回的json对象转化成相应的实体类从而存储到数据库中。(如果对每个成员变量进行判断,会很麻烦,就使用反射来实现)
public static void main(String[] args) {
	JSONObject json = new JSONObject();
	AssetInfo assetInfo = new AssetInfo();
	json.put("name", "sun");
	json.put("num", "23");
	reflectEntity(assetInfo,json);
	System.out.println(assetInfo.getName()+"*********"+assetInfo.getNum());
}

public static void reflectEntity(AssetInfo assetInfo,JSONObject  json){
	Class ca = assetInfo.getClass();
	for(Iterator<String> iter = json.keys();iter.hasNext();){
		String key = iter.next();
		Object value = json.get(key);
		if(value != null){
			try {
				//在assetInfo实体类的类类型中获取到json相应key的Field对象
				Field field = null;
				field = ca.getDeclaredField(key);
				field.setAccessible(true);
				String type = field.getType().getName();
				//根据类型进行set操作
				if(type.endsWith("String")){
					field.set(assetInfo, json.getString(key));
				}else{
                                //省略。。。
                                }
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}


代码质量写的不忍直视哈,主要看一下反射的应用:
上面代码很好理解,就是每次循环json对象,取得相应的key值到实体类中找到相应的Fiels对象,找到后存储相应的value值到成员变量的set方法中。

一、Class类
1.在面向对象的世界中:万事万物皆为对象
那么每次我们新建的类是不是对象?
答案是:新建的.java类也是对象-->是java.lang.Class类的实例对象。

2.这个对象是如何表示的呢?
官方的说法是该类的类类型
比如我们在工程中新建的AssetInfo.java类如何表示成java.lang.Class类的实例对象。
①任何一个类都有一个隐含的静态成员变量class
 
Class c1 = AssetInfo.class;

②已知该类的实例化对象(以上面的代码为例)
 
Class c2 = assetInfo.getClass();

c1,c2表示的是AssetInfo.java的类类型(class type)
同时AssetInfo.java类也有自己的实例对象就是assetInfo
那么此时if(c1==c2)? 答案是true:一个类只能是Class类的一个实例对象

③动态加载类类型的方法
Class c3 = Class.forName("com.reflect.testDemo");//是包含包名的完整路径

通过以上的方式能够得到该类的类类型,并且根据类类型可以创建该类的实例对象:
AssetInfo ai = (AssetInfo)c1.newInstance();//做一个强制转换

c1=c2=c3

3.类的动态加载
类有两种加载方式:动态加载和静态加载
①动态加载:编译时刻不去加载类,运行时刻去加载使用的类
Class c = Class.forName("类的全称");//这种方式是动态加载的,不仅仅表示了该类的类类型
AssetInfo ai = (AssetInfo)c.newInstance();//实例化对象


②静态加载:编译时刻就去加载所有可能使用的类的方式
关键字new来实例化对象就是静态加载
AssetInfo ai = new AssetInfo();


如果使用Eclipse并不太好区分编译和运行,如果想看动态加载和静态加载的区别最好自己写使用doc编译和运行
如果使用静态方法实例化对象,并且没有提供相应的类,那么在编译的过程中就是会报错的。
而使用动态加载类的方式,即使不提供相应的类,编译也是可以通过,在运行时候才会报错。

4.基本数据类型
Class c1 = int.class;//int的类类型
Class c2 = String.class;//String的类类型
//一个类中的所有关键字都存在类类型
c1.getName();//类的全称,带包名
c2.getSimpleName();//不包含包名

5.Class基本API
要取得类的相应的信息,必须先获得该类的类类型,通过类类型再去获取类的成员变量成员函数等信息。
①类的成员方法:java.lang.reflect.Method;封装了关于成员函数的操作信息
public static void classMethodMessage(Object obj){
	Class c = obj.getClass();
	c.getName();//类的名称
	Method[] ms = c.getMethods();//所有的public的函数,包括父类继承而来的
	Method[] ms = c.getDeclaredMethods();//获取所有该类自己声明的方法
	ms[0].getName();//获取该方法的名称
	Class returnType = ms[0].getReturnType();//获取返回值的类类型
	returnType.getName();//获取返回值的名称
	Class[] paramTypes = ms[0].getParameterTyprs();//获取方法的参数列表的类类型
	paramType[0].getName()//参数类型的名称
}

②类的成员变量:java.lang.reflect.Fiels;封装了关于成员变量的操作信息
public static void classFieldMessage(Object obj){
	Class c = obj.getClass();
	Field[] fs = c.getFields();//获取所有public的成员变量
	Field[] fs = c.getDeclaredFields();//获取该类自己声明的所有成员变量
	fs[0].getName();//获取成员变量名
	Class fieldType = fs[0].getType();//获取成员变量类型的类类型 --> int.class
	fieldType.getName();//获取成员变量类型的名称
}

③类的构造函数:java.lang.reflect.Constructor;封装了构造函数的操作信息
public static void classConstructorMessage(Object obj){
	Class c = obj.getClass();
	Constructor[] cs = c.getConstructors();//获取所有public的构造函数
	Constructor[] cs = c.getDeclaredConstructors();//获取所有的构造函数
	cs[0].getName();//获取构造函数名称
	Class[] paramTypes = cs[0].getParameterTypes();//获取构造函数的参数列表的类类型
	paramTypes[0].getName();//获取参数列表的名称
}

Class中有很多的方法,可以去参考一下API
二、方法的反射
1.获取某个方法
如果我们想通过反射的方式来获取到相应的方法需要什么必须条件呢?
方法的名称和方法的参数列表能够唯一决定某个方法

2.方法调用
通过反射方式取得该方法如何调用呢?
method.invoke(对象,参数列表);
public void userMethod(Object obj){
	Class c = obj.getClass();
	Method m = c.getDeclaredMethod("printMsg",int.class,int.class);//获取相应的方法,两种写法
	Method m = c.getDeclaredMethod("printMsg",Class[]{int.class,int.class}); 
	Object o = m.invoke(obj,10,15);//调用方法,如果有返回值返回具体的返回值,没有返回值返回null,有以下两种写法
	Object o = m.invoke(obj,Object[]{10,15});
}

public void printMsg(int a,int b){
        System.out.println(a+b);
}

3.认识泛型的本质
因为是动态加载的方式,所以反射的操作都是编译之后的操作
ArrayList list = new ArrayList();
ArrayList<String> list1 = new ArrayList<String>();
Class c1 = list.getClass();
Class c2 = list1.getClass();

if(c1==c2)-->true : 说明编译之后的集合都是去泛型的
java中的泛型只是为了防止错误的输入,只在编译有效,绕过编译就无效了
Method m = c2.getMethod("add",Object.class);//获取ArrayList类的add方法
m.invoke(list1,1);//调用该方法向list1中添加一个int类型,查看是否能成功,list1有泛型规范只能添加String
list1.size();//list 的大小是1,表示插入成功了。说明反射绕过了泛型成功添加了数据。


三、应用
最后奉上我们组大神的反射代码,原谅我有点没看懂 差距不是一点半点呵呵
/**
 * 
 * [将一个bean中字段值 copy至另一个bean相应字段中,]

 *
 * @comment	[注释说明]
 *
 * @param <T>
 * @param originalBean
 * @param targetClazz 必须包含默认构造方法
 * @return
 */
public static <T> T copyBean2Another(Object originalBean ,Class<T> targetClazz)
{
	if(targetClazz == null || originalBean == null)
	{
		throw new UniEAPBusinessException("空指针");
	}
	Class<?> originalClass = originalBean.getClass();
	Method[] targetMethods = targetClazz.getMethods();
	Constructor<T>[] targetConstructors = (Constructor<T>[]) targetClazz.getConstructors();
	TypeVariable<Constructor<T>>[] typeVariableArray = null;
	Constructor<T> targetConstructor = null;
	for(Constructor<T> tempConstructor : targetConstructors)
	{
		typeVariableArray = tempConstructor.getTypeParameters();
		if(typeVariableArray == null || typeVariableArray.length < 1)
		{
			targetConstructor = tempConstructor;
			break;
		}
	}
	if(targetConstructor == null)
	{
		throw new UniEAPBusinessException("目标类中没有默认构造方法");
	}
	T a = null;
	try
	{
		a = targetConstructor.newInstance();
		String fieldName = null;
		Method orginalBeanGetMethod = null;
		for(Method tempTargetMethod : targetMethods)
		{
			if(tempTargetMethod.getName().startsWith("set"))
			{
				fieldName = tempTargetMethod.getName().substring(3);
				try
				{
					orginalBeanGetMethod = originalClass.getMethod("get" + fieldName);
					tempTargetMethod.invoke(a, orginalBeanGetMethod.invoke(originalBean));
				}
				catch (Throwable e)
				{
					if(logger.isInfoEnabled())
					{
						logger.info(originalClass.getName() + "中没有get" + fieldName + "方法");
					}
				}
			}
		}
	}
	catch (IllegalArgumentException e)
	{
		logger.error(e.getMessage(), e);
		throw new UniEAPBusinessException("目标类中没有默认构造方法");
	}
	catch (InstantiationException e)
	{
		logger.error(e.getMessage(), e);
		throw new UniEAPBusinessException("目标类中没有默认构造方法");
	}
	catch (IllegalAccessException e)
	{
		logger.error(e.getMessage(), e);
		throw new UniEAPBusinessException("目标类中没有默认构造方法");
	}
	catch (InvocationTargetException e)
	{
		logger.error(e.getMessage(), e);
		throw new UniEAPBusinessException("目标类中没有默认构造方法");
	}
	return a;
}


欢迎大家吐槽。。。。
1
0
分享到:
评论
2 楼 elena_me 2015-12-03  
把json转成bean不用反射也可以吧
1 楼 wst0350 2015-11-02  
学习了

相关推荐

    Java 反射机制 代码的实例

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部结构。通过反射,开发者可以动态地获取类的信息并调用其方法,创建对象,访问私有成员,甚至改变类的行为。在深入...

    反射实例-JAVA反射机制

    ### 反射实例—JAVA反射机制 #### 一、反射概念及原理 反射在计算机科学领域,特别是程序设计中,是指程序有能力访问、检测和修改其自身的结构和行为。这一概念最早由Smith于1982年提出,并迅速应用于各种编程语言...

    Java反射机制总结(实例分析)

    Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并进行操作。通过反射,开发者可以在程序执行时发现并访问类的字段(fields)、方法(methods)以及构造器(constructors),...

    Java反射机制 Java反射机制

    Java反射机制的主要作用包括:获取类的所有属性和方法、构造动态实例、调用类的方法等。通过反射,程序可以动态地创建对象和调用其方法,从而实现更灵活的功能。 #### 二、Java反射机制的由来与发展 Java反射机制...

    JAVA反射机制的入门代码

    Java反射机制是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在处理元数据、创建对象、调用私有方法...

    反射实例-JAVA反射机制.doc

    Java 反射机制详解 Java 反射机制是 Java 语言提供的一种强大的工具,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并进行操作。这种能力使得 Java 应用程序更加灵活,能够在运行时发现和修改自身...

    Java 反射机制实例详解

    Java 反射机制实例详解 Java 反射机制实例详解是一种动态语言机制,允许在程序运行时加载、探知和使用编译期间完全不知道的类、生成其对象实体,调用其方法或者对属性设值。下面是 Java 反射机制实例详解的知识点:...

    Java反射机制的详细讲解及实例,有助于java深度开发

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段和方法等对象。这一机制对于理解和利用Java的动态性至关重要,尤其是在进行复杂系统设计、框架开发以及元数据驱动的应用中...

    java反射经典实例

    通过上述实例,我们可以看到Java反射机制在许多实际场景中的应用,它扩展了Java代码的灵活性和可扩展性。然而,也应注意,过度使用反射可能会引入复杂性和潜在的安全风险,因此在设计和实现时需权衡利弊。在理解了...

    Java反射机制总结

    ### Java反射机制总结 #### 反射的概念与起源 反射的概念最早由Smith于1982年提出,指的是程序能够访问、检测并修改其自身状态或行为的能力。这一概念的提出迅速引起了计算机科学领域的广泛关注,并在之后的研究中...

    java 反射机制详解

    Java 反射机制是 Java 语言中的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并调用对象的方法,甚至修改对象的状态。这一机制极大地增强了 Java 程序的灵活性和可扩展性,尤其是在...

    Java反射动态加载实例类

    ### Java反射机制与动态加载实例类 在Java中,反射是一种强大的工具,允许程序在运行时检查和修改其结构和行为。通过反射,我们可以动态地加载类、创建对象、访问和修改字段、调用方法等。本文将深入探讨Java反射...

    候捷谈Java反射机制

    Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取和操作任何已知名称的类的内部信息。这一机制使得Java具备了一定的动态性,虽然在传统的分类中Java被视为静态类型语言。通过反射,开发者可以在...

    Java反射机制学习(二)

    在"Java反射机制学习(二)"这篇博文中,作者可能详细解释了以上这些概念,并通过`BaseTest.java`和`Student.java`这两个示例文件进行了实例演示。`BaseTest.java`可能包含了一组基础的反射操作,而`Student.java`...

    通过Java反射机制获取JavaBean对象

    1.通过Java反射机制获取JavaBean对象。 2.通过JavaBean全路径字符串获取JavaBean对象。 3.获取JavaBean注解信息

    Java反射机制Demo

    ### Java反射机制详解 #### 一、什么是Java反射机制? Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的...

    一个例子让你了解Java反射机制

    Java反射机制是Java编程语言中的一个重要特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类集中在java.lang.reflect包下,包括Class、Constructor、Method和...

Global site tag (gtag.js) - Google Analytics