java反射

获取到Class对象的三种方法:

 Class clazz = String.class;
Class clazz = javaTest".getClass();
Class clazz = Class.forName("java.lang.String");//常用

获取到类加载器:

ClassLoader classLoader = ClassLoader.getSystemClassLoader();//系统ClassLoader
classLoader = Class.forName("com.atguigu.java.fanshe.ReflectionTest")
             .getClassLoader();//当然类由哪个ClassLoader加载的

获取类的方法:

/  1.1 获取取clazz对应类中的所有方法--方法数组(一)
        //     不能获取private方法,且获取从父类继承来的所有方法
        Method[] methods = clazz.getMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName());
        }
//  1.2.获取所有方法,包括私有方法 --方法数组(二)
        //  所有声明的方法,都可以获取到,且只获取当前类的方法
        methods = clazz.getDeclaredMethods();
        for(Method method:methods){
            System.out.print(" "+method.getName());
        }
 //  1.3.获取指定的方法
        //  需要参数名称和参数列表,无参则不需要写
        //  对于方法public void setName(String name) {  }
        Method method = clazz.getDeclaredMethod("setName", String.class);
        System.out.println(method);
        //  而对于方法public void setAge(int age) {  }
        method = clazz.getDeclaredMethod("setAge", Integer.class);
        System.out.println(method);
        //  这样写是获取不到的,如果方法的参数类型是int型
        //  如果方法用于反射,那么要么int类型写成Integer: public void setAge(Integer age) {  }
     //  要么获取方法的参数写成int.class

获取方法的参数和返回值:

System.out.print("方法名:" + method.getName() + " 返回值类型:" + method.getReturnType().getName());
//获取某个方法的所有参数
            Class[] cls = method.getParameterTypes();
            if (cls.length != 0) {
                for (int j = 0; j < cls.length; j++) {
                    System.out.println(" 方法的参数:" + cls[j].getName());
                }
            } else {
                System.out.println(" ***该方法无参数");
            }

使用方法:

//2.执行方法
        //  invoke第一个参数表示执行哪个对象的方法,剩下的参数是执行方法时需要传入的参数
        Object obje = clazz.newInstance();
        method.invoke(obje,2);

    //如果一个方法是私有方法,第三步是可以获取到的,但是这一步却不能执行
    //私有方法的执行,必须在调用invoke之前加上一句method.setAccessible(true);

获取到字段field:

@Test
    public void testField() throws Exception{
        String className = "com.atguigu.java.fanshe.Person";        
        Class clazz = Class.forName(className); 
        
        //1.获取字段
      //  1.1 获取所有字段 -- 字段数组
        //     可以获取公用和私有的所有字段,但不能获取父类字段
        Field[] fields = clazz.getDeclaredFields();
        for(Field field: fields){
            System.out.print(" "+ field.getName());
        }
        System.out.println();
        
        //  1.2获取指定字段
        Field field = clazz.getDeclaredField("name");
        System.out.println(field.getName());
        
        Person person = new Person("ABC",12);
        
        //2.使用字段
      //  2.1获取指定对象的指定字段的值
        Object val = field.get(person);
        System.out.println(val);
        
        //  2.2设置指定对象的指定对象Field值
        field.set(person, "DEF");
        System.out.println(person.getName());
        
        //  2.3如果字段是私有的,不管是读值还是写值,都必须先调用setAccessible(true)方法
        //     比如Person类中,字段name字段是公用的,age是私有的
        field = clazz.getDeclaredField("age");
        field.setAccessible(true);
        System.out.println(field.get(person));        
    }

但是如果需要访问父类中的(私有)字段:

/**
     * //创建 className 对应类的对象, 并为其 fieldName 赋值为 val
     * //Student继承自Person,age是Person类的私有字段/
     public void testClassField() throws Exception{
        String className = "com.atguigu.java.fanshe.Student";
        String fieldName = "age"; //可能为私有, 可能在其父类中. 
        Object val = 20;        
        
        Object obj = null;
        //1.创建className 对应类的对象
        Class clazz = Class.forName(className);
        //2.创建fieldName 对象字段的对象
        Field field = getField(clazz, fieldName);
        //3.为此对象赋值
        obj = clazz.newInstance();
        setFieldValue(obj, field, val);
        //4.获取此对象的值
        Object value = getFieldValue(obj,field);
    }
    
    public Object getFieldValue(Object obj, Field field) throws Exception{
        field.setAccessible(true);
        return field.get(obj);
    }

    public void setFieldValue(Object obj, Field field, Object val) throws Exception {
        field.setAccessible(true);
        field.set(obj, val);
    }

    public Field getField(Class clazz, String fieldName) throws Exception {
        Field field = null;
        for(Class clazz2 = clazz; clazz2 != Object.class;clazz2 = clazz2.getSuperclass()){        
                field = clazz2.getDeclaredField(fieldName);
        }
        return field;
    }

使用ClassLoader加载文件:

//src目录下,直接加载
        InputStream in1 = null;
        in1 = this.getClass().getClassLoader().getResourceAsStream("test1.txt");
        
        //放在内部文件夹,要写全路径
        InputStream in2 = null;
        in2 = this.getClass().getClassLoader().getResourceAsStream("com/atguigu/java/fanshe/test2.txt");

例子:

package com.self.test;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DemoTest {
  public static void main(String[] args) {
    try {
      Class class2 = Class.forName("com.self.entity.Person");
      // 获取到所有本身的方法名
      Method[] methods = class2.getDeclaredMethods();
      for (Method method : methods) {
        System.out.println(method.getName());
      }
      // 获取指定method
      Method method = class2.getDeclaredMethod("setSex", String.class);
      // 创建对象
      Object o = class2.newInstance();
      method.invoke(o,"hehe");
      System.out.println(o);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    }


  }
}

借鉴于:https://www.cnblogs.com/tech-bird/p/3525336.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章