欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

通过反射来剖析类的构成

程序员文章站 2024-01-20 16:02:46
...

类的构成:
构造方法:Constructor
成员变量:Field
成员方法:Method

获取构造方法对象;


		//先获取到该类的字节码文件对象
        Class clazz = Class.forName("org.westos.demo2.Student");
        
        //getConstructors():获取该类中所有的构造方法对象,私有的除外
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
       
        
        //getDeclaredConstructors(); 获取所有的构造方法对象,包括私有的
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
      

        //获取空参的构造方法对象
        Constructor constructor = clazz.getConstructor();
        
        //获取一个参数的构造方法对象,传入参数的class类型,不能获取私有的
        Constructor constructor1 = clazz.getConstructor(String.class);
        
        //获取私有的构造方法对象getDeclaredConstructor(String.class, int.class);
        Constructor constructor2 = clazz.getDeclaredConstructor(String.class, int.class);
student类:
public class Student {
    public Student(){
        System.out.println("空参构造");
    }

    public Student(String name) {
        System.out.println("有参构造"+name);
    }

    private Student(String name,int age) {
        System.out.println("私有的有参构造" + name+"==="+age);
    }
}

同上的应用:
 		//获取该类的字节码文件对象
        Class aClass = Class.forName("org.westos.demo2.Student");

        //获取空参的构造方法对象
        Constructor constructor = aClass.getConstructor();

        //通过构造方法对象中的 newInstance() 来创建出该类的一个实例
        Student obj = (Student) constructor.newInstance();


        //通过有参构造来创建该类的实例
        Constructor constructor1 = aClass.getConstructor(String.class);
        Object o = constructor1.newInstance("张三");
        
        //通过私有的构造创建该类的对象
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true); //取消语法检测
        Object o1 = declaredConstructor.newInstance("王五", 25);

获取类的字段对象:


		//获取该类的字节码文件对象
        Class aClass = Student.class;

        //获取类中的所有的字段对象
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        //getDeclaredFields() 获取类中所有的字段对象,包括私有
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        //获取单个的字段
        Field name = aClass.getField("name");

        //获取私有的字段对象
        Field sex = aClass.getDeclaredField("sex");



student类:
public class Student {
    public String name;
    public int age;
    private char sex;
}

同上的应用:
		//获取字节码文件对象
Class<?> aClass = Class.forName("org.westos.demo3.Student");
        
        Field field = aClass.getField("name");
        Object obj = aClass.getConstructor().newInstance();
        

        //给字段设置值
        field.set(obj,"张三");
        
        //获取字段的值
        Object o = field.get(obj);


        //给私有字段设置值
        Field sex = aClass.getDeclaredField("sex");
        //对于私有可以取消语法检测
        sex.setAccessible(true); 
        sex.set(obj,'男');
        Object o1 = sex.get(obj);
        Character character= (Character) o1;

获取方法对象:

	 Class<?> aClass = Class.forName("org.westos.demo4.Student");
        //获取所有的方法对象,包括父类的方法对象,私有除外
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        
        //获取该类的所有方法对象,包括私有的方法
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }

        
        //获取单个的方法对象,参数1,方法名;参数2:这个方法上的参数的字节码类型
        Method hehe = aClass.getMethod("hehe");
        System.out.println(hehe);
        Method haha = aClass.getMethod("haha", String.class);
        System.out.println(haha);
        Method test = aClass.getMethod("test", String.class,int.class);
        System.out.println(test);

        //获取私有的方法对象
        Method method = aClass.getDeclaredMethod("method", String.class, int.class);
        System.out.println(method);
public class Student {
    public void test(){
        System.out.println("这是一个空参方法");
    }

    public int test(String name) {
        System.out.println("这是一个参数方法");
        return 100;
    }

    public int test(String name,int a) {
        System.out.println("这是两个参数的方法");
        return 100+a;
    }

    private int method(String name, int a) {
        System.out.println("这是一个私有的方法");
        return 100 + a;
    }
}

应用:
 		//通过反射机制,调用类中的方法执行

        Class<?> aClass = Class.forName("org.westos.demo4.Student");

        //获取该方法的对象
        Method test = aClass.getMethod("test");
        Object obj = aClass.getConstructor().newInstance();

        //通过方法对象中的 invoke() 让这个方法执行
        test.invoke(obj);



        Method haha = aClass.getMethod("test", String.class);
        //让一个参数的方法 执行 也可以拿到该方法的返回值
        Object o1 = haha.invoke(obj, "王五");

        //让两个参数的方法执行
        Method test1 = aClass.getMethod("test", String.class, int.class);
        Object o2 = test1.invoke(obj, "张三", 23);

        //让私有的方法执行
        Method method = aClass.getDeclaredMethod("method", String.class, int.class);
        method.setAccessible(true);//取消语法检测
        Object value = method.invoke(obj, "李四", 24);

应用实例:

		 //基于狗类开发
      
        
        Properties properties = new Properties();
        
        //从配置文件中读取全限定名和方法名,易于修改,方便维护;
        properties.load(new FileInputStream("peizhi.properties"));
        
        //属性集合读取指定键对应的类名;
        String className = properties.getProperty("className");
        //获取类字节码文件对象;
        Class<?> aClass = Class.forName(className);
        
       
        //如果你使用空参构造来创建对象
        //Class对象里面newInstance()这个方法,可以创建该类的对象
        Object o1 = aClass.newInstance();
        Method methodName = aClass.getDeclaredMethod(properties.getProperty("methodName"));
        methodName.invoke(o1);

狗类:
public class Dog {
    public void eat(){
        System.out.println("狗吃骨头");
    }

    public void sleep() {
        System.out.println("狗睡觉");
    }
}

下图是配置文件内容:

通过反射来剖析类的构成

另外,泛型只在编译器有效,运行期就自动擦除了,应用如下:

//ArrayList<Integer> 想在这个集合中添加一个字符串数据,如何实现呢?
ArrayList<Integer> integers = new ArrayList<>();
        integers.add(100);
        //越过泛型检测,只能在运行期,反射在运行期的一种机制

        Class<? extends ArrayList> aClass = integers.getClass(); //ArrayList.class
        Method add = aClass.getDeclaredMethod("add", Object.class);

        add.invoke(integers,"abc");
        System.out.println(integers);