本文主要通过Java反射应用实例来讲解 利用反射方法创建对象(使用默认构造函数和自定义构造函数) ,访问对应对象的方法(包括带参数的和不带参数的),访问对应对象的域(Field) . 从 这里 可以下载到完整的java代码工程: http://download.csdn.net/detail/hejiangtao/4011663
很多IOC等框架都使用反射来实现,例如Spring, Hibernate等, Java反射的方式实现的逻辑比普通类逻辑的效率是要差一些的(14至300倍左右), 具体可以参考我转载的一篇文章<java反射的性能问题>http://blog.csdn.net/hejiangtao/article/details/7188835.
首先看下我们实例中被访问的类DataTypeBean.java:
这个Bean中定义了4种类型的Field,包含了int, String,String数组和List; 定义了默认构造函数和自定义的构造函数; 还有一个给List域赋值的带参数函数; 一个不带参数的toString函数.我们要实现的就是使用反射的方法来访问这些Fields 和Methods.
- package com.ross.reflect.bean;
- import java.util.*;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Date: 2012-1-4
- * Since: MyJavaExpert v1.0
- * Description: It will contains some typical fields whose data types
- * are using frequently. it will be used in the reflect test
- */
- public class DataTypeBean
- {
- private int iInt;
- private String sStr;
- private String[] saStr;
- List< Integer > oList;
- // default constructor
- public DataTypeBean()
- {
- }
- // constructor with parameters
- public DataTypeBean(int iInt, String sStr, String[] saStr,
- List< Integer > oList)
- {
- this.iInt = iInt;
- this.saStr = saStr;
- this.sStr = sStr;
- this.oList = oList;
- }
- // method with parameter, it will set value of the list field
- public void addDataToList(int iStart, int iEnd)
- {
- if (iStart < iEnd )
- {
- oList = new ArrayList < Integer > ();
- while (iStart < = iEnd)
- {
- oList.add(iStart);
- iStart++;
- }
- }
- }
- // method without parameter
- public String toString()
- {
- StringBuffer sbStr = new StringBuffer();
- sbStr.append("Values of the fields of DataTypeBean: iInt = ");
- sbStr.append(this.iInt).append(" ; ");
- for (int i = 0 ; i < this.saStr.length ; i++)
- {
- sbStr.append("saStr").append("[").append(i).append("]").append(
- " = ").append(saStr[i]).append(" ; ");
- }
- for (int j = 0 ; j < this.oList.size (); j++)
- {
- sbStr.append("oList.get").append("(").append(j).append(")").append(
- " = ").append(oList.get(j)).append(" ; ");
- }
- return sbStr.toString();
- }
- //省略了set/get方法
- }
来看我们的反射的实现类MyReflect.java, 由于担心代码太长不好看,就全部在Main函数里面写了,方便看.
1. 首先我们看下使用默认构造函数创建类对象, 并通过访问Field对象来给类对象赋值, 最后通过toString方法打印字符串.
初始化我们要使用的参数, 这些参数将用于给类的Field赋值:
获取 DataTypeBean的类,和我们将要用到的方法对象, 其中toString方法是不带参数的,addDataToList则是带参数的. 由此可以看出我们在使用反射方法的时候是需要知道参数个数和参数类型的:
- int iInt = 2012 ;
- String sStr = "This a string!" ;
- String[] saStr = new String[] { "First item of the string array",
- "Second item of the string array",
- "Third item of the string array" };
- List< Integer > oList = new ArrayList < Integer > ();
- // Initialize the oList
- int i = 0 ;
- while (i < 3 )
- {
- oList.add(i);
- i++;
- }
使用默认构造函数创建一个 DataTypeBean的对象:
- // get class
- Class oClass = Class.forName("com.ross.reflect.bean.DataTypeBean");
- // get the toString method, a method without parameters
- Method oToStringMethod = oClass .getMethod("toString");
- // get the addDataToList method, a method with parameters
- Method oAddDataToListMethod = oClass .getMethod("addDataToList",
- int.class, int.class);
使用反射方法访问Field来给对象赋值:
- // used default constructor to initialize a object
- Object oDefalutObject = oClass .newInstance();
通过反射方法调用 DataTypeBean的toString方法将赋值后的 DataTypeBean打印出来:
- // access fields process, getDeclaredFields can access private and
- // protected fields
- Field[] oFields = oClass .getDeclaredFields();
- for (int j = 0 ; j < oFields.length ; j++)
- {
- // to access the private
- oFields[j].setAccessible(true);
- // getSimpleName method can get the type of the field, according the
- // field type set the data to the field
- if ("int".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].setInt(oDefalutObject, iInt);
- }
- else if ("String[]".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, saStr);
- }
- else if ("String".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, sStr);
- }
- else if ("List".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, oList);
- }
- }
运行后,我们的控制台打印出如下信息:
- // print the object
- String sBeanString = (String) oToStringMethod.invoke(oDefalutObject);
- System.out
- .println("the string of the object created by defaut constructor: "
- + sBeanString);
- the string of the object created by defaut constructor: Values of the fields of DataTypeBean: iInt = 2012 ;
- saStr[0] = First item of the string array ; saStr[1] = Second item of the string array ; saStr[2] = Third item
- of the string array ; oList.get(0) = 0 ; oList.get(1) = 1 ; oList.get(2) = 2 ;
2. 我们再看下使用自定义构造函数创建类对象, 并通过带参数的函数给其List域赋值, 最后通过toString方法打印字符串.
变更下我们要用的参数, 好在控制台上跟默认构造函数创建的对象的打印信息做区分:
使用自定义构造函数创建类对象:
- // initialize the parameters for customized constructor, the oList will
- // be initialized by the method with parameters
- iInt = 2013 ;
- sStr = "This another string!" ;
- saStr = new String[] { "1st item of the string array",
- "2nd item of the string array", "3rd item of the string array" };
- oList = new ArrayList < Integer > ();
使用带参数的函数给List 域赋值:
- // used customized constructor to initialize a object: DataTypeBean(int
- // iInt, String sStr, String[] saStr, List< Integer > oList)
- Constructor oCon = oClass .getConstructor(int.class, String.class,
- String[].class, List.class);
- Object oCustomizedObject = oCon .newInstance(iInt, sStr, saStr, oList);
同样的,通过反射方法调用 DataTypeBean的toString方法将赋值后的 DataTypeBean打印出来:
- //Use the method with parameters initialize the List Object
- oAddDataToListMethod.invoke(oCustomizedObject,2013,2015);
运行后,我们的控制台打印如下信息:
- // print the object
- sBeanString = (String) oToStringMethod.invoke(oCustomizedObject);
- System.out
- .println("the string of the object created by customized constructor: "
- + sBeanString);
- the string of the object created by customized constructor: Values of the fields of DataTypeBean: iInt = 2013 ;
- saStr[0] = 1st item of the string array ; saStr[1] = 2nd item of the string array ; saStr[2] = 3rd item of the
- string array ; oList.get(0) = 2013 ; oList.get(1) = 2014 ; oList.get(2) = 2015 ; oList.get(3) = 2016 ;
为了方便参考,我将完整的MyReflect.java贴出来了:
- package com.ross.reflect;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Date: 2012-1-9
- * Since: MyJavaExpert v1.0
- * Description: reflect method implementation and test
- */
- public class MyReflect
- {
- /**
- * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
- * Date: 2012-1-9
- * Description: Use reflect method to access the fields and methods of DataTypebean
- */
- public static void main(String[] args) throws ClassNotFoundException,
- SecurityException, NoSuchMethodException, InstantiationException,
- IllegalAccessException, IllegalArgumentException,
- InvocationTargetException
- {
- int iInt = 2012 ;
- String sStr = "This a string!" ;
- String[] saStr = new String[] { "First item of the string array",
- "Second item of the string array",
- "Third item of the string array" };
- List< Integer > oList = new ArrayList < Integer > ();
- // Initialize the oList
- int i = 0 ;
- while (i < 3 )
- {
- oList.add(i);
- i++;
- }
- // get class
- Class oClass = Class.forName("com.ross.reflect.bean.DataTypeBean");
- // get the toString method, a method without parameters
- Method oToStringMethod = oClass .getMethod("toString");
- // get the addDataToList method, a method with parameters
- Method oAddDataToListMethod = oClass .getMethod("addDataToList",
- int.class, int.class);
- // used default constructor to initialize a object
- Object oDefalutObject = oClass .newInstance();
- // access fields process, getDeclaredFields can access private and
- // protected fields
- Field[] oFields = oClass .getDeclaredFields();
- for (int j = 0 ; j < oFields.length ; j++)
- {
- // to access the private
- oFields[j].setAccessible(true);
- // getSimpleName method can get the type of the field, according the
- // field type set the data to the field
- if ("int".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].setInt(oDefalutObject, iInt);
- }
- else if ("String[]".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, saStr);
- }
- else if ("String".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, sStr);
- }
- else if ("List".equals(oFields[j].getType().getSimpleName()))
- {
- oFields[j].set(oDefalutObject, oList);
- }
- }
- // print the object
- String sBeanString = (String) oToStringMethod.invoke(oDefalutObject);
- System.out
- .println("the string of the object created by defaut constructor: "
- + sBeanString);
- // initialize the parameters for customized constructor, the oList will
- // be initialized by the method with parameters
- iInt = 2013 ;
- sStr = "This another string!" ;
- saStr = new String[] { "1st item of the string array",
- "2nd item of the string array", "3rd item of the string array" };
- oList = new ArrayList < Integer > ();
- // used customized constructor to initialize a object: DataTypeBean(int
- // iInt, String sStr, String[] saStr, List< Integer > oList)
- Constructor oCon = oClass .getConstructor(int.class, String.class,
- String[].class, List.class);
- Object oCustomizedObject = oCon .newInstance(iInt, sStr, saStr, oList);
- //Use the method with parameters initialize the List Object
- oAddDataToListMethod.invoke(oCustomizedObject,2013,2015);
- // print the object
- sBeanString = (String) oToStringMethod.invoke(oCustomizedObject);
- System.out
- .println("the string of the object created by customized constructor: "
- + sBeanString);
- }
- }
![大笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/laugh.gif)