Java反射应用实例

本文主要通过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赋值:

        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的类,和我们将要用到的方法对象, 其中toString方法是不带参数的,addDataToList则是带参数的. 由此可以看出我们在使用反射方法的时候是需要知道参数个数和参数类型的:

        // 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);
使用默认构造函数创建一个 DataTypeBean的对象:

        // used default constructor to initialize a object
        Object oDefalutObject = oClass.newInstance();
使用反射方法访问Field来给对象赋值:

        // 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);
            }
        }
通过反射方法调用 DataTypeBean的toString方法将赋值后的 DataTypeBean打印出来:

        // 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>();
使用自定义构造函数创建类对象:

        // 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);
使用带参数的函数给List 域赋值:

       //Use the method with parameters initialize the List Object
        oAddDataToListMethod.invoke(oCustomizedObject,2013,2015);
同样的,通过反射方法调用 DataTypeBean的toString方法将赋值后的 DataTypeBean打印出来:

 // 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://hejiangtao.iteye.com/  用于商业得给我分成大笑
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值