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;
}
欢迎大家吐槽。。。。
分享到:
相关推荐
Java 反射机制 代码的实例 请认真阅读 运行此代码 只要读懂了 反射机制也就明白了
反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc反射实例-JAVA反射机制.doc...
Java反射机制总结(实例分析) Java反射机制学习笔记
这是一本关于Java反射机制论文集合的书。其中包含基本的理论及各种实例。... 关键字有:Java Java反射机制 Java反射 Java反射理论 Java反射实例 Java反射例子 反射原理 反射 网络论文 集合 汇总 总结 Class。
Java 反射机制、Java 的类反射机制、Java 反射机制的学习、Java 反射Reflection--运行时生成实例 java反射机制的手册文档
JAVA反射机制与类的加载,详细的说明java反射机制的实例以及应用是入门级的课件
1.通过Java反射机制获取JavaBean对象。 2.通过JavaBean全路径字符串获取JavaBean对象。 3.获取JavaBean注解信息
java反射机制应用,文档中列举了使用java反射机制的各个应用场景,加以代码实例,使用学习非常方便。
java的反射机制的应用实例,对反射的机制很好的理解!
反射实例-JAVA反射机制
Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件 之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内 部信息,而不是...
本实例教程分反射对成员变量、构造器、方法操作,详尽而简略得列出反射机制的应用,希望对大家有用。
主要介绍了Java 反射机制实例详解的相关资料,这里对java中反射机制进行了详细的分析,需要的朋友可以参考下
一个java反射的例子,通过java反射机制,动态生成java实例,动态执行方法。例子中有大量注释,简单易懂。
java反射原理,反射机制原理,以及java反射机制实现实例!希望能给大家一点帮助!
代码为JAVA反射的一个DEMO,适合初学者临摹学习,还附有properties的创建方法,比较基础。
主要介绍了Java 反射机制的实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握反射机制,需要的朋友可以参考下
有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。我们朗朗上口动态绑定(dynamic binding)、动态链接(dynamic ...是可以通过反射机制来实现“动态”,用一个实例来说明一下: