反射
什么是反射?反射的作用
反射是利用类的加载机制,对类进行动态操作的一种体现,操作类的成员属性和方法(一般都是公共的)。
反射的作用:在现在的J2EE应用领域中所使用的较多,一般都采用反射来对“类和表的映射文件”进行动态解析并实例化的操作,常见于ORM映射技术中。有时也在一些轻量级容器中能见到此技术的应用,比如Spring。总之,J2EE中一般都能见到此技术的运用。普通的反射效率较低,但可操作性较强,有时候也配合动态代理技术来完成相关运用。
实例化步骤
1. 调用Class中的forName()方法根据类名实例化一个Object类型的对象
2. 强制转化成所需类型
利用反射的知识拼装sql语句 原来在DAO中的操作如下: Insert into usertb valuse(user.getName,user.getPwd)
改成反射动态拼装,如何做? 已知条件:已赋值的对象 |
见到“class...”说明此处的参数是类型数组,如果见到“object…”说明此处的参数是对象数组
利用反射的一些例子
反射的方法
SoftDevoloper.java
SoftDevoloper.java |
package com.ibm.dto;
public class SoftDevoloper { /** * 软件工程师 * @param devId * @param devName * @param age */
public SoftDevoloper(int devId,String devName,int age){ this.devId=devId; this.devName=devName; this.age=age; }
public SoftDevoloper(){
}
//编号 privateint devId; //名称 private StringdevName; //年龄 privateint age; //技能 private String[]skill;
publicint getDevId() { returndevId; } publicvoid setDevId(int devId) { this.devId = devId; } public String getDevName() { return devName; } public void setDevName(String devName) { this.devName = devName; } publicint getAge() { returnage; } public void setAge(int age) { this.age = age; }
public String[] getSkill() { returnskill; }
public void setSkill(String[] skill) { this.skill = skill; }
}
|
ArgDemo.java
package com.ibm.test;
/** * 反射中方法多个参数的调用类 * @author Administrator * */ public class ArgDemo {
/** * 说话 * @param uname用户 * @param msg说的内容 * @param len说的长度 */ public void say(String uname,String msg,int len){
System.out.println(uname+"说"+msg+"一共"+len+"个长度"); }
}
|
Test.java
Test.java |
package com.ibm.test;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
import com.ibm.dto.SoftDevoloper;
public class Test {
publicvoid GetInstance() {
//生成一个开发人员的实例对象 Object obj; try { obj = Class.forName("com.ibm.dto.SoftDevoloper").newInstance(); //强制转换成所需类型 SoftDevoloper sdl=(SoftDevoloper)obj; sdl.setDevName("詹姆斯"); System.out.println(sdl.getDevName());
} catch (ClassNotFoundException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { //TODO Auto-generated catch block e.printStackTrace(); } } /** * 测试获取类中的方法 * @param args */ publicvoid testMethod() { try { //根据类名找到对象 Class sodCls=Class.forName("com.ibm.dto.SoftDevoloper"); //返回方法数组 Method[] method=sodCls.getDeclaredMethods(); //循环操作方法 for (Method method2 : method) { System.out.println("方法名是:"+method2.getName());
} } catch (ClassNotFoundException e) { e.printStackTrace(); } }
/** * 操作属性 */ public void testField(){
Class sodCls; try { sodCls = Class.forName("com.ibm.dto.SoftDevoloper");
Field[] field=sodCls.getDeclaredFields();
for(Field field2:field){ System.out.println("属性名:"+field2.getName()); }
} catch (ClassNotFoundException e) { e.printStackTrace(); } }
/** * 类中构造器 * @param args */ publicvoid testConst(){
Class sodCls; try { sodCls = Class.forName("com.ibm.dto.SoftDevoloper"); Constructor[] constr=sodCls.getConstructors();
for(Constructor constructor:constr){ System.out.println("构造器:"+constructor.getName()); } } catch (ClassNotFoundException e) { e.printStackTrace(); }
}
/** * 方法的操作 */ publicvoid methodOperDemo(){
SoftDevoloper sd=null; Class cls=null; Method method=null; try { //实例化 sd = new SoftDevoloper(1,"java", 18); //根据类名实例化类对象 cls = Class.forName("com.ibm.dto.SoftDevoloper"); //找到get方法 method=cls.getMethod("getDevName"); //调用invoke方法获得返回值 Object retVal = method.invoke(sd,null); System.out.println("返回值是:"+retVal);
} catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
}
/** * 采用反射动态赋值 * @param from原对象 * @param to目标对象 * @throws NoSuchMethodException * @throws SecurityException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */ public void copy(Object from,Object to)throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
Class fromCls=from.getClass();
Class toCls=to.getClass();
Field[] field=fromCls.getDeclaredFields();
for(Field field2:field){ //所有属性名 String fieldName=field2.getName(); //get方法 String getMethodName="get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); //set方法 String setMethodName="set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); //根据方法名找到具体的方法 Method method=fromCls.getMethod(getMethodName,null);
//获得get方法所返回的值 Object objValue=method.invoke(from,null);
//返回值类型根据返回值类型来确定set方法中参数的类型 Class clsType=method.getReturnType();
Method setMethod=toCls.getMethod(setMethodName, clsType);
//将从from对象中取到值给to对象 setMethod.invoke(to, objValue); } }
(此处调用的是ArgDemo类) /** * 测试根据名称、参数来找方法 */ public void testArg(){ try { Class cls=Class.forName("com.ibm.test.ArgDemo");
Object obj=cls.newInstance();
String methodName="say"; //找到方法 Method method=cls.getDeclaredMethod(methodName,new Class[]{String.class,String.class,int.class});
//调用方法并依次赋参数 method.invoke(obj, new Object[]{"犀利哥","今年我要上春晚",7}); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { //TODO Auto-generated catch block e.printStackTrace(); }
}
public staticvoid main(String[] args) { Test test = new Test(); test.GetInstance(); test.testMethod(); test.testField();
test.testConst();
test.methodOperDemo();
SoftDevoloper sd1=new SoftDevoloper(); sd1.setDevName("bill"); sd1.setDevId(123); sd1.setAge(10);
SoftDevoloper sd2 = new SoftDevoloper(); //将值从sd1复制到sd2中 try { test.copy(sd1, sd2); } catch (SecurityException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { //TODO Auto-generated catch block e.printStackTrace(); } //获得sd2对象中的值 System.out.println(sd2.getDevName()); System.out.println(sd2.getDevId()); System.out.println(sd2.getAge());
test.testArg(); }
} |
利用反射实现对输入框获取到的值进行输出
FormToDtoUtil.java
FormToDtoUtil.java |
package com.ibm.util;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.Date; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
public class FormToDtoUtil {
/** * 将request对象中的值传递到DTO对象中 * @param request请求对象 * @param to赋值对象 * @throws NoSuchFieldException * @throws SecurityException * @throws NoSuchMethodException * @throws ParseException * @throws InvocationTargetException * @throws IllegalAccessException * @throws IllegalArgumentException */
publicvoid load(HttpServletRequest request ,Object to)throws SecurityException, NoSuchFieldException, NoSuchMethodException, ParseException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
//getPatameterNames表示获得表单中控件的名称集合 //枚举对象和迭代性质一样 Enumeration enumera=request.getParameterNames(); //获得to对象的类实例 Class toCls=to.getClass();
while (enumera.hasMoreElements()) { String elem = (String) enumera.nextElement(); System.out.println("控件名是:"+elem); String[] value=request.getParameterValues(elem);
if(value!=null){ //获得属性类型 Class type=toCls.getDeclaredField(elem).getType(); //获得属性对应的set方法 因为控件名是和dto中的属性是一致的,所以可以直接使用控件名来代替属性名 String setMethodName="set"+elem.substring(0,1).toUpperCase()+elem.substring(1); System.out.println("set的名字是:"+setMethodName); //根据方法名称找到set方法 Method method=toCls.getDeclaredMethod(setMethodName, type);
Object[] obj=objectConvert(value, type);
//如果遇到数组类型 if(type.isArray()){ //遇到的类型是数组类型 则直接将数组赋值给to对象 method.invoke(to,new Object[]{obj}); }else{ //非数组类型则 按照数组索引格式取出值,然后赋值即可 method.invoke(to, new Object[]{obj[0]}); }
} }
}
/** * 数据转换方法因为dto中的属性类型不确定,只能针对所有需要的类型进行判断才能返回 * 所需要的类型 * @param value表单中所获取的值 * @param FieldType DTO中字段的类型 * @return返回对象默认以对象数组的格式返回 * @throws ParseException */
publicstatic Object[] objectConvert(String[] value,Class FieldType)throws ParseException{
Object[] obj=new Object[value.length];
if(FieldType==Integer.class||FieldType==int.class){ obj[0]=Integer.parseInt(value[0]); }elseif(FieldType==Date.class){ SimpleDateFormat format =new SimpleDateFormat("yyyy-MM-dd"); obj[0]=format.parse(value[0]); }else{ obj=value; } return obj; }
}
|
RegAction.java
RegAction.java |
package com.ibm.action;
import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.text.ParseException; importjava.text.Normalizer.Form; importjava.util.Enumeration;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import com.ibm.dto.SoftDevoloper; import com.ibm.util.FormToDtoUtil;
public classRegAction extends HttpServlet {
/** * Constructor of the object. */ public RegAction() { super(); }
/** * Destruction of the servlet.<br> */ publicvoid destroy() { super.destroy();// Just puts "destroy" string in log // Put your code here }
/** * The doGet method of theservlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ publicvoid doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html"); PrintWriter out = response.getWriter(); out .println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); out.print(" This is "); out.print(this.getClass()); out.println(", using the GET method"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
/** * The doPost method of theservlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//实例化开发人员对象未赋值 SoftDevoloper sd= new SoftDevoloper(); //动态赋值 FormToDtoUtil ftd= new FormToDtoUtil();
try { ftd.load(request, sd);
System.out.println("获得的值是:"+sd.getDevName());
} catch (SecurityException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (ParseException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { //TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { //TODO Auto-generated catch block e.printStackTrace(); }
}
/** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ publicvoid init()throws ServletException { // Put your code here }
}
|