Java Reflection 反射通用经典实例

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 ";
 }
}


Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射反射机制是如今很多流行框架的实现基础,其中包括Spring、Hibernate等。原理性的问题不是本文的重点,接下来让我们在实例中学习这套精彩的机制。 1. 得到某个对象的属性 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; } Class ownerClass = owner.getClass():得到该对象的Class。 Field field = ownerClass.getField(fieldName):通过Class得到类声明的属性。 Object property = field.get(owner):通过对象得到该属性的实例,如果这个属性是非公有的,这里会报IllegalAccessException。 2. 得到某个类的静态属性 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; } Class ownerClass = Class.forName(className) :首先得到这个类的Class。 Field field = ownerClass.getField(fieldName):和上面一样,通过Class得到类声明的属性。 Object property = field.get(ownerClass) :这里和上面有些不同,因为该属性是静态的,所以直接从类的Class里取。 3. 执行某对象的方法 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); } Class owner_class = owner.getClass() :首先还是必须得到这个对象的Class。 3~6行:配置参数的Class数组,作为寻找Method的条件。 Method method = ownerClass.getMethod(methodName, argsClass):通过Method名和参数的Class数组得到要执行的Method。 method.invoke(owner, args):执行该Method,invoke方法的参数是执行这个方法的对象,和参数数组。返回值是Object,也既是该方法的返回值。 4. 执行某个类的静态方法 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); } 基本的原理和实例3相同,不同点是最后一行,invoke的一个参数是null,因为这是静态方法,不需要借助实例运行。 5. 新建实例 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); } 这里说的方法是执行带参数的构造函数来新建实例的方法。如果不需要参数,可以直接使用newoneClass.newInstance()来实现。 Class newoneClass = Class.forName(className):第一步,得到要构造的实例的Class。 第6~第10行:得到参数的Class数组。 Constructor cons = newoneClass.getConstructor(argsClass):得到构造子。 cons.newInstance(args):新建实例。 6. 判断是否为某个类的实例 public boolean isInstance(Object obj, Class cls) { return cls.isInstance(obj); } 7. 得到数组中的某个元素 public Object getByArray(Object array, int index) { return Array.get(array,index); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值