Java Reflection 反射通用经典实例

来源:互联网 发布:windows fifo 读写文件 编辑:程序博客网 时间:2024/06/08 08:07

package cn.com.common;

 
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.apache.log4j.Logger;

public class ReflectObject implements Serializable{

 private static final long serialVersionUID = 1L;

 private static Logger logger = Logger.getLogger(ReflectObject.class);
 
 private String className;
    private String methodName;
 private Class<?>[] paramTypes;
 private Object[] paramValues;

 /**
  * OK 
  * 1.Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射
  * 如果返回结果 为false,说明方法执行失败
  * 调用的方法没有返回值时,返回的结果也是空 所以返回结果为空 不能作为判断 方法被调用的条件
  * @param className  传入的类名称
  * @param methodName 传入类中要调用的方法名称
  * @param paramTypes 传入变量的类型 类  (例如  String.class, int.class)
  * @param paramValues 传入变量的值  (例如 "", 20) 值的类型必须和变量类型保持一致
  * @return 如果返回结果 为false,说明方法执行失败  ; 返回 空(调用的方法没有返回值时,返回的结果为空) 或 有值 都说明方法已经执行
  */
 private Object getReflectObject(String className, String methodName,
   Class<?>[] paramTypes, Object[] paramValues) {
  String reflectClassMethod = "Reflect Calss Name: " + className + " --> Reflect Method Name: " + methodName;
  
  logger.debug(this.getClass().getName() + " -->\n " + reflectClassMethod + "\n paramTypes:" + paramTypes +"\n paramValues:" + paramValues);
        // 参数有效性判断
  if (className == null || className.trim().length() == 0) {
   logger.debug(this.getClass().getName() + " --> Reflect Calss Name is null ");
   return false;
  }

  if (methodName == null || methodName.trim().length() == 0) {
   logger.debug("Reflect Calss Name: " + className + " --> Reflect Method Name is null ");
   return false;
  }

  Class<?> clazzName = null;
        try {
   clazzName = Class.forName(className);
   Method method = clazzName.getMethod(methodName, paramTypes);
   Object object = method.invoke(clazzName.newInstance(), paramValues);
            logger.debug(className + " --> Return Reflect Result: " + object);
           
   return object;
  } catch (Exception e) {
   e.printStackTrace();
   logger.debug(reflectClassMethod + " --> (paramTypes or paramValues is matchError ) Exception: " +e.getMessage());
   return false;
  }
    }

 /**
  * OK
  * 2.得到某个对象的公共属性
  * Class ownerClass = owner.getClass():得到该对象的Class。
  * Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。
  *  Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。
  *
  * @param owner, fieldName
  * @return 该属性对象
  * @throws Exception
  */
 public Object getProperty(Object owner, String fieldName) throws Exception {
  Class<?> ownerClass = owner.getClass();
  Field field = ownerClass.getField(fieldName);
  Object property = field.get(owner);
  return property;
 }

 /** OK
  * 3.得到某个类的静态属性
  * Class ownerClass = Class.forName(className) :首先得到这个类的Class。
  * Field field = ownerClass.getField(fieldName):和上面一样,通过Class得到类声明的属性。
  * Object property = field.get(ownerClass)  :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。
  *
  * @param className 类名
  * @param fieldName 属性名
  * @return 该属性对象
  * @throws Exception
  */
 public Object getStaticProperty(String className, String fieldName)
   throws Exception {
  Class<?> ownerClass = Class.forName(className);
  Field field = ownerClass.getField(fieldName);
  Object property = field.get(ownerClass);
  return property;
 }

 /**
  * 4.执行某对象的方法
  * Class owner_class = owner.getClass() :首先还是必须得到这个对象的Class。
  * 配置参数的Class数组,作为寻找Method的条件。 Method method = ownerClass.getMethod(methodName, argsClass):通过Method名和参数的Class数组得到要执行的Method。
  * method.invoke(owner, args):执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既是该方法的返回值。
  *
  * @param owner 对象
  * @param methodName 方法名
  * @param args 参数
  * @return 方法返回值
  * @throws Exception
  */
    public Object invokeMethod(Object owner, String methodName, Object[] args)
   throws Exception {
  Class<?> ownerClass = owner.getClass();
  
  Class<?>[] argsClass = new Class[args.length];
  for (int i = 0, j = args.length; i < j; i++) {
   argsClass[i] = args[i].getClass();
  }
  Method method = ownerClass.getMethod(methodName, argsClass);
  
  return method.invoke(owner, args);
 }

 /**
  * 5.执行某个类的静态方法
  * 基本的原理和实例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。
  *
  * @param className 类名
  * @param methodName 方法名
  * @param args 参数数组
  * @return 执行方法返回的结果
  * @throws Exception
  */
 public Object invokeStaticMethod(String className, String methodName,
   Object[] args) throws Exception {
  Class<?> ownerClass = Class.forName(className);
       
  Class<?>[] argsClass = new Class[args.length];
        for (int i = 0, j = args.length; i < j; i++) {
   argsClass[i] = args[i].getClass();
  }
        Method method = ownerClass.getMethod(methodName, argsClass);

  return method.invoke(null, args);
 }

 /**
  * OK
  * 6.新建实例   (注意new Object[]{} 的值不能写成 null 否则报 空指针异常)
  * @param className  类名
  * @param args 构造函数的参数
  * @return 新建的实例
  * @throws Exception
  */
 public Object newInstance(String className, Object[] args) throws Exception {
  Class<?> newoneClass = Class.forName(className);

  Class<?>[] argsClass = new Class[args.length];
  for (int i = 0, j = args.length; i < j; i++) {
   argsClass[i] = args[i].getClass();
  }
        Constructor<?> cons = newoneClass.getConstructor(argsClass);
       
  return cons.newInstance(args);
 }

 /**
  * OK
  * 7.是不是某个类的实例
  * @param obj 实例
  * @param cls 类
  * @return 如果 obj 是此类的实例,则返回 true
  */
 public boolean isInstance(Object obj, Class<?> cls) {
  return cls.isInstance(obj);
 }

 /**
  * OK
  * 8.得到数组中的某个元素  (注意 后面数字过大,会报数组下标越界的异常)
  * @param array  数组
  * @param index  索引
  * @return 返回指定数组对象中索引组件的值
  */
 public Object getByArray(Object array, int index) {
  return Array.get(array, index);
 }

 /**
  * OK
  * 9.copyObj(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性复制到新建的对象中,并将它返回
  * @param object
  * @return
  * @throws Exception
  */
 public Object copyObj(Object object) throws Exception {
  // 获得对象的类型
  Class<?> classType = object.getClass();
  logger.debug(this.getClass().getName() + " --> Class:" + classType.getName());
  // 通过默认构造方法创建一个新的对象
  Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
  // 获得对象的所有属性
  Field fields[] = classType.getDeclaredFields();
  for (int i = 0; i < fields.length; i++) {
   Field field = fields[i];
   String fieldName = field.getName();
   String firstLetter = fieldName.substring(0, 1).toUpperCase();
   // 获得和属性对应的getXXX()方法的名字
   String getMethodName = "get" + firstLetter + fieldName.substring(1);
   // 获得和属性对应的setXXX()方法的名字
   String setMethodName = "set" + firstLetter + fieldName.substring(1);
   // 获得和属性对应的getXXX()方法
   Method getMethod = classType.getMethod(getMethodName,
     new Class[] {});
   // 获得和属性对应的setXXX()方法
   Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
   // 调用原对象的getXXX()方法
   Object value = getMethod.invoke(object, new Object[] {});
   logger.debug(classType.getClass().getName() + " --> " + fieldName + ":" + value);
   // 调用复制对象的setXXX()方法
   setMethod.invoke(objectCopy, new Object[] { value });
  }
  return objectCopy;
 }
 
 /**
  * 10.获取反射类中的属性和属性值
  * @param object
  */
 public void getPropertyNameAndValue(Object object) {
  Class<?> clazz = object.getClass();
  try {
   System.out.println("反射类中所有公有的属性");
   Field[] fb = clazz.getFields();
   for (int j = 0; j < fb.length; j++) {
    Class<?> cl = fb[j].getType();
    System.out.println("public: " + cl);
   }

   System.out.println("反射类中所有的属性");
   Field[] fa = clazz.getDeclaredFields();
   for (int j = 0; j < fa.length; j++) {
    Class<?> cl = fa[j].getType();
    System.out.println("all :" + cl);
   }
   System.out.println("反射类中私有属性的值");
   Field f = clazz.getDeclaredField("int");
   f.setAccessible(true);
   Integer i = (Integer) f.get(object);
   System.out.println(i);
  } catch (Exception e) {
   e.printStackTrace();
   logger.debug(this.getClass().getName() + " --> Class:" + clazz.getName());
  }
 }

 /**
  * 11.获取反射类中的构造方法
  * @param object
  */
 public void printConstructors(Object object) {
  Class<?> c = object.getClass();
  // 获取指定类的类名
  String className = c.getName();
  try {
   // 获取指定类的构造方法
   Constructor<?>[] theConstructors = c.getConstructors();
   for (int i = 0; i < theConstructors.length; i++) {
    // 获取指定构造方法的参数的集合
    Class<?>[] parameterTypes = theConstructors[i].getParameterTypes();
                System.out.print(className + "(");
                for (int j = 0; j < parameterTypes.length; j++)
     System.out.print(parameterTypes[j].getName() + " ");

    System.out.println(")");

   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 /**
  * 12.获取一下反射类的父类(超类)和接口
  * @param o
  */
 public void printInterfaceNames(Object o) {
  Class<?> c = o.getClass();
  // 获取反射类的接口
  Class<?>[] theInterfaces = c.getInterfaces();
  for (int i = 0; i < theInterfaces.length; i++)
   System.out.println(theInterfaces[i].getName());
  // 获取反射类的父类(超类)
  Class<?> theSuperclass = c.getSuperclass();
  System.out.println(theSuperclass.getName());
 }

 /**
  * 13.获取反射类的所有方法,包括继承自它父类的方法。然后获取方法的返回类型、方法名和方法参数。
  * @param o
  */
 public void printMethods(Object o) {
  Class<?> c = o.getClass();
  //String className = c.getName();
  Method[] m = c.getMethods();
  for (int i = 0; i < m.length; i++) {
   // 输出方法的返回类型
   System.out.print(m[i].getReturnType().getName());
   // 输出方法名
   System.out.print(" " + m[i].getName() + "(");
   // 获取方法的参数
   Class<?>[] parameterTypes = m[i].getParameterTypes();
   for (int j = 0; j < parameterTypes.length; j++) {
    System.out.print(parameterTypes[j].getName());
    if (parameterTypes.length > j + 1) {
     System.out.print(",");
    }
   }

   System.out.println(")");
  }

 }

 /**
  * 14.Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库
  * @param className
  * @param methodName
  * @param types
  * @param params
  * @return
  */
 public Object loadObject(String className, String methodName, String[] types,
   String[] params) {
  Object retobj = null;
  try {
   // 加载指定的Java类
   Class<?> cls = Class.forName(className);

   // 获取指定对象的实例
   Constructor<?> ct = cls.getConstructor(null);
   Object obj = ct.newInstance(null);

   // 构建方法参数的数据类型
   Class<?> partypes[] = this.getMethodClass(types);

   // 在指定类中获取指定的方法
   Method meth = cls.getMethod(methodName, partypes);

   // 构建方法的参数值
   Object arglist[] = this.getMethodObject(types, params);

   // 调用指定的方法并获取返回值为Object类型
   retobj = meth.invoke(obj, arglist);

  } catch (Throwable e) {
   System.err.println(e);
  }
  return retobj;
 }

 /**
  * 获取参数类型Class[]的方法
  * @param types
  * @return
  */
 public Class<?>[] getMethodClass(String[] types) {
  Class<?>[] clazzs = new Class[types.length];
  for (int i = 0; i < clazzs.length; i++) {
   if (!types[i].trim().equals("") || types[i] != null) {
    if (types[i].equals("int") || types[i].equals("Integer")) { //int or Integer
     clazzs[i] = Integer.TYPE;
    } else if (types[i].equals("float") || types[i].equals("Float")) { //float  or  Float
     clazzs[i] = Float.TYPE;
    } else if (types[i].equals("double") || types[i].equals("Double")) { //double  or  Double
     clazzs[i] = Double.TYPE;
    } else if (types[i].equals("boolean") || types[i].equals("Boolean")) { //boolean  or  Boolean
     clazzs[i] = Boolean.TYPE;
    } else {
     clazzs[i] = String.class;
    }
   }
  }
  return clazzs;
 }
  
 /**
  * 获取参数Object[]的方法
  * @param types
  * @param params
  * @return
  */
 public Object[] getMethodObject(String[] types, String[] params) {
  Object[] objs = new Object[params.length];
  for (int i = 0; i < objs.length; i++) {
   if (!params[i].trim().equals("") || params[i] != null) {
    if (types[i].equals("int") || types[i].equals("Integer")) { //int or Integer
     objs[i] = new Integer(params[i]);
    } else if (types[i].equalsIgnoreCase("float")) { //float  or  Float
     objs[i] = new Float(params[i]);
    } else if (types[i].equalsIgnoreCase("double")) {//double  or  Double
     objs[i] = new Double(params[i]);
    } else if (types[i].equalsIgnoreCase("boolean")) {//boolean  or  Boolean
     objs[i] = new Boolean(params[i]);
    } else {
     objs[i] = params[i];
    }
   }
  }
  return objs;
 }
 
 public String getClassName() {
  return className;
 }

 public void setClassName(String className) {
  this.className = className;
 }

 public String getMethodName() {
  return methodName;
 }

 public void setMethodName(String methodName) {
  this.methodName = methodName;
 }

 public Class<?>[] getParamTypes() {
  return paramTypes;
 }

 public void setParamTypes(Class<?>[] paramTypes) {
  this.paramTypes = paramTypes;
 }

 public Object[] getParamValues() {
  return paramValues;
 }

 public void setParamValues(Object[] paramValues) {
  this.paramValues = paramValues;
 }

 public static void main(String[] args) throws Exception {
  ReflectObject tc = new ReflectObject();
//  //1.Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射 OK
  String className = "cn.com.common.TestDemo";
  String methodName = "getString";
  Class<?>[] ptypes = new Class<?>[]{String.class, String.class, int.class};
  Object[] objs = new Object[]{"Zhang San", " 男 ", 25};
  System.out.println("1 -->"+tc.getReflectObject(className, methodName, ptypes, objs));
        //2.得到某个对象的公共属性    OK  注意 必须传入对象
  System.out.println("2 -->"+tc.getProperty(new TestDemo(), "name"));
  //3.得到某个类的静态属性  OK
  System.out.println("3 -->"+ tc.getStaticProperty("cn.com.common.TestDemo", "pass"));
     //4.执行某对象的方法  OK         注意 此方法中的参数类型 必须为对象
  System.out.println("4 -->"+tc.invokeMethod(new TestDemo(), "getStringDesc", new Object[]{"Zhang San", " 男 ", 25})); //new Integer(22);   Integer  age
  //5.执行某个类的静态方法 OK      注意 此方法中的参数类型 必须为对象
  System.out.println("5 -->"+tc.invokeStaticMethod("cn.com.common.TestDemo", "getStringTest", new Object[]{"Zhang San", " 男 ", 25}));
  //6.新建实例 OK                 注意new Object[]{} 的值不能写成 null 否则报 空指针异常, 必须有显示的构造方法
  System.out.println("6 -->"+((TestDemo)tc.newInstance("cn.com.common.TestDemo", new Object[]{})).name);
  //7.是不是某个类的实例 OK
  System.out.println("7 -->"+tc.isInstance(new ReflectObject() , ReflectObject.class));
  //8.得到数组中的某个元素 OK      注意 后面数字过大,会报数组下标越界的异常
  System.out.println("8 -->"+tc.getByArray(new Object[]{"Zhang San", " 男 ", 25}, 2));
  //9.copy(Object object)方法,这个方法能够创建一个和参数object同样类型的对象,然后把object对象中的所有属性复制到新建的对象中,并将它返回
  TestDemo td = new TestDemo();
  td.setName("hu jing tao");
  System.out.println("Copy Object information:" + tc.copyObj(td));
  //10.获取反射类中的属性和属性值
  tc.getPropertyNameAndValue(new TestDemo());
  //11.获取反射类中的构造方法
  tc.printConstructors(new TestDemo()) ;
  //12.获取一下反射类的父类(超类)和接口
  tc.printInterfaceNames(new TestDemo());
  //13.获取反射类的所有方法,包括继承自它父类的方法。然后获取方法的返回类型、方法名和方法参数
  tc.printMethods(new TestDemo());
  //14.loadObject方法接收的五个参数分别是,Java的类名,方法名,参数的类型和参数的值。
        tc.loadObject( className, methodName, new String[]{"String","String", "int"}, new String[]{"qq","ww","12"});
 }

}
/**
 * 此类不能为内部类
 * @author Administrator
 *
 */
class TestDemo {
 public String name = "nameDesc";
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }

 public static String pass = "passDesc";
    public static String getPass() {
  return pass;
 }
 public static void setPass(String pass) {
  TestDemo.pass = pass;
 }
 public TestDemo(){}
 public TestDemo(String name){}
 public String getString(String name, String sex, int age) {
//  System.out.println(this.getClass().getName() + " --> " + name + sex + age + " getString(String name, String sex, int age) OK ");
     return this.getClass().getName() + " --> " + name + sex + age + " getString(String name, String sex, int age) OK";
 }

 public String getStringDesc(String name, String sex, Integer age) {
//  System.out.println(this.getClass().getName() + " --> " + name + sex + age + " getStringDesc(String name, String sex, Integer age) OK ");
     return this.getClass().getName() + " --> " + name + sex + age + " getStringDesc(String name, String sex, Integer age) OK ";
 }

 public static String getStringTest(String name, String sex,  Integer age) {
//  System.out.println("Test --> " + name + sex + age + " getStringTest(String name, String sex, Integer age) OK ");
  return "Test --> " + name + sex + age + " getStringTest(String name, String sex, Integer age) OK ";
 }
}


原创粉丝点击