① 创建对象
    如果知道一个类型,很容易使用new操作符创建一个类的实例。但是如果在编译时并不知道具体要实例化的是哪个类的对象,如何创建该实例呢?
    Java中提供Class.forName(String className)从一个字符串(含包的类全名称)加载一个类,再利用newInstance方法创建该类的实例。 

//动态创建类对象  
public static Object createObject(String className) {  
    Object object = null;  
    try {  
        Class classDefinition = Class.forName(className);  
        object = classDefinition.newInstance();  
    } catch (InstantiationException e) {  
        System.out.println(e);  
    } catch (IllegalAccessException e) {  
        System.out.println(e);  
    } catch (ClassNotFoundException e) {  
        System.out.println(e);  
    }  
    return object;  
}



当然,也可以先获取一个类的Constructor,再调用其newInstance方法创建对象。不同的是,constructor对象的newInstance方法需要传递一个对象数组作为构造方法的参数列表。


//使用Constructor动态创建对象  
public static Object createObject(Constructor constructor, Object[] arguments) {  
    System.out.println("Constructor: " + constructor.toString());  
    Object object = null;  
    try {  
        object = constructor.newInstance(arguments);  
        System.out.println("Object: " + object.toString());  
        return object;  
    } catch (InstantiationException e) {  
        System.out.println(e);  
    } catch (IllegalAccessException e) {  
        System.out.println(e);  
    } catch (IllegalArgumentException e) {  
        System.out.println(e);  
    } catch (InvocationTargetException e) {  
        System.out.println(e);  
    }  
    return object;  
}

② 获取/设置字段值


    利用Reflection API获取或者设置字段的值,首先要得到Class对象,然后利用Class对象的getField方法取得相应的字段Field对象,然后调用Field对象对应的getXXX/setXXX方法获取或者设置属性的值。Filed对象提供getInt/setInt、getLong/setLong等方法对基本类型的属性进行值的获取和设置,可以直接使用get/set方法获取复杂类型属性的值(返回一个对象值/传递一个对象值作为参数)。


    具体操作方法见如下代码片段。当然,若试图获取/设置一个非public的字段值(getField方法也不能获取非pubic的属性对象,可以尝试使用getDeclaredField方法),将产生IllegalAccessException,可以通过setAccessible(true)使非public的字段可见,然后对字段值进行访问。

// 获取字段值  
        static void getFiledValue(Object o, String filedName) {  
            Class c = o.getClass();  
            Field filed;  
            Object value;  
            try {  
                filed = c.getField(filedName);  
    //          filed = c.getDeclaredField(filedName);  
    //          filed.setAccessible(true);  //修改字段访问权限  
                value = filed.get(o);   //可使用getInt、getLong等(若知晓字段基本类型)  
                System.out.println(filedName + ": " + value.toString());  
            } catch (NoSuchFieldException e) {  
                System.out.println(e);  
            } catch (SecurityException e) {  
                System.out.println(e);  
            } catch (IllegalAccessException e) {  
                System.out.println(e);  
            }  
        }



// 修改字段值  
    public static void setFieldValue(Object o, String filedName, Object value) {  
        Field filed;  
        Class c = o.getClass();  
        try {  
            filed = c.getField(filedName);  
//          filed = c.getDeclaredField(filedName);  
//          filed.setAccessible(true);  //修改字段访问权限  
            filed.set(o, value);    //可使用setInt、setLong等(若知晓字段基本类型)  
        } catch (NoSuchFieldException e) {  
            System.out.println(e);  
        } catch (IllegalAccessException e) {  
            System.out.println(e);  
        }  
    }




③ 调用方法


    方法调用的过程类似于设置字段值的过程,首先要得到Class对象,然后调用getMethod方法得到方法Method的对象,getMethod方法要求传递两个参数,一个是方法名,第二个是Class[],即方法参数列表中各参数对应的类型的数组。然后执行Method对象的invoke方法,进行方法的调用,invoke方法需要传递两个参数,第一个是方法绑定的对象,第二个是方法的参数列表。如果是static的方法,则第一个参数将自动被忽略(可为null)。


    同理,对于非public的方法,可以使用getDeclaredMethod方法获取Method对象,并使用setAccessible设置其可见性。 

//动态调用方法  
    public static Object callMethod(Object o, String methodName,  
            Class paramsType[], Object paramsValue[]) {  
        Object result = null;  
        Class c;  
        Method method;  
        try {  
            c = o.getClass();  
            method = c.getMethod(methodName, paramsType);  
//          method = c.getDeclaredMethod(methodName, paramsType);  
//          method.setAccessible(true);  
            result = method.invoke(o, paramsValue);  
        } catch (NoSuchMethodException e) {  
            System.out.println(e);  
        } catch (IllegalAccessException e) {  
            System.out.println(e);  
        } catch (InvocationTargetException e) {  
            System.out.println(e);  
        }  
        return result;  
    }