java反射

public class Test_Reflection {

 public static void main(String[] args) throws ClassNotFoundException {
  //TestReflection tf = new TestReflection();
  //有些时候,我们并不一定能够直接去new对象
  //然后获取对象里面的属性
  //所以只能通过对象的名字,或者对象本身,反过来去查找对象的所有的属性
  //反过来找,其实就是通过反射找到每个对象对应的class对象
 

 

 
  //获得class对象有三种方式
  //1.编译器已经知道类的名字
  Class c1 = TestReflection.class;
  //2.已经获得了类的对象
  TestReflection tf = new TestReflection();
  Class c2 = tf.getClass();
  //3.通过运行期获取class
  Class c3 = Class.forName("test.TestReflection");

  //获取包名
  String packageName = c1.getPackage().getName();
  System.out.println(packageName);

 

  //获取的类的权限修饰符
  int mod = c1.getModifiers();
  String modifier = Modifier.toString(mod);
  
  //获取类的全名
  String className = c1.getName();
  
  System.out.println(modifier + " " + className);
  
  //获取类的父类
  Class superClass = c1.getSuperclass();
  System.out.println(Modifier.toString(superClass.getModifiers())
    + " class " + superClass.getName());
  
  //获取父接口
  Class [] is = c1.getInterfaces();
  
  for(Class t : is){
   System.out.println(Modifier.toString(t.getModifiers())
     + " interface " + t.getName());
  }

 
  //获得成员变量
  Field [] fs = c1.getDeclaredFields();
  
  for(Field f : fs){
   //获得每个字段访问修饰符
   String mods = Modifier.toString(f.getModifiers());
   //获得每个字段的类型
   Class type = f.getType();
   //获得类型名
   String typeName = type.getName();
   //获得字段名
   String fieldName = f.getName();
   
   //如果是数组,需要判断
   if(type.isArray()){
    typeName = type.getComponentType().getName() + "[]";
   }
   
   System.out.println(mods + " " + typeName + " " + fieldName);
   
  }
  

 
  //获得构造方法
  Constructor [] cs = c1.getDeclaredConstructors();
  for(Constructor c : cs){
   //获得构造方法的名字
   String cName = c.getName();
   //获得构造方法的修饰符
   String cMod = Modifier.toString(c.getModifiers());
   //获得构造方法中的参数
   Class [] paramTypes = c.getParameterTypes();
   
   System.out.print(cMod + " " + cName + "(");
   
   for(int i=0; i<paramTypes.length; i++){
    if( i > 0 ){
     System.out.print(",");
    }
    //如果是数组需要特殊处理
    if(paramTypes[i].isArray()){
     System.out.print(paramTypes[i].getComponentType().getName() + "[]");
    }else{
     System.out.print(paramTypes[i].getName());
    }
   }
   
   System.out.println(")");
  }

 

  
  System.out.println("----------------成员方法----------------");
  //获得成员方法
  Method [] methods = c1.getDeclaredMethods();
  //遍历所有的成员方法
  for(Method m : methods){
   //获取访问修饰符
   String mmod = Modifier.toString(m.getModifiers());
   
   //获取方法的返回值类型
   Class rType = m.getReturnType();
   String returnType = "";
   if(rType.isArray()){
    returnType = rType.getComponentType().getName() + "[]";
   }else{
    returnType = rType.getName();
   }
   
   //获取方法名
   String mname = m.getName();
   //获取参数
   Class [] paramTypes = m.getParameterTypes();
   
   System.out.print(mmod + " " + mname + "(");
   
   for(int i=0; i<paramTypes.length; i++){
    if( i > 0 ){
     System.out.print(",");
    }
    //如果是数组需要特殊处理
    if(paramTypes[i].isArray()){
     System.out.print(paramTypes[i].getComponentType().getName() + "[]");
    }else{
     System.out.print(paramTypes[i].getName());
    }
   }
   
   System.out.println(")");
  }

 

  System.out.println("--------------通过反射调用方法----------------");
  
  //我们还可以通过反射直接去调用方法
  //可以通过Method类中的invoke方法实现动态的调用
  //public Object invoke(Obejct,Object...args)
  //第一个参数表示对象
  //第二个参数开始是表示方法需要传入的参数
  
  //之前其实已经获得了c1,c2,c3这几个Class对象,其实我们可以直接将Class对象再转化为实例化对象
  try {
   //这里实例化的是不带参的构造方法
   TestReflection tf1 = (TestReflection)c1.newInstance();
   tf1.name = "张三";
   tf1.password = "1111";
   System.out.println(tf1.name + "  " + tf1.password);
   
   //通过Class实例化带参的构造方法
   //通过构造方法实例化,其实需要先实例化构造方法对象
   Constructor cons = c3.getConstructor(new Class[]{String.class,String.class,int[].class});
   //实例化构造方法对象
   Object obj = cons.newInstance(new Object[]{"李四","abcd",new int[]{99,100,88}});
   //将构造方法对象转换为具体实例化对象
   TestReflection tf2 = (TestReflection)obj;
   System.out.println(tf2.name + " " + tf2.password + " " + tf2.score[1]);
   
   
   //通过反射调用方法
   Method m1 = c3.getDeclaredMethod("setName", String.class);
   m1.invoke(tf2, "王五");
   System.out.println(tf2.name);
   
   //通过反射调用带数组的方法
   Method m2 = c3.getDeclaredMethod("setScore", int[].class);
   int [] nums = {1,2,4};
   m2.invoke(tf2, nums);
   System.out.println(tf2.score[1]);
   
   //通过反射调用private修饰的方法
   Method m3 = c3.getDeclaredMethod("setPassword", String.class);
   m3.setAccessible(true);
   m3.invoke(tf2, "9999");
   System.out.println(tf2.password);
   
  } catch (InstantiationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IllegalAccessException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (NoSuchMethodException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SecurityException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IllegalArgumentException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (InvocationTargetException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 
 }

}

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、付费专栏及课程。

余额充值