初识反射

反射:Reflection

  对象------>类信息

  反射可以使程序在运行时获取一个类的所有信息(构造器、属性、方法),从而做相应操作。反射其实就是将Java类中的每一个成分映射成一个个Java对象。要想通过反射获取类包含的成分,必须先获取字节码文件对应的Class对象。

  

Class类表示什么?

  很多的人---可以定义一个Person类(有年龄、性别、姓名等)

  很多的车---可以定义一个Car类(有发动机、车轮等)

  很多的--Class类(类名、构造方法、属性、方法)

 

class对象的是 .class文件读入内存时,创建的一个对象

得到Class类的对象有三种方法:

  (1)对象.getClass() 

  (2)类.class

  (3)Class.forName("全类名")        最常用的方式

 

例如:

package com.reflection;

import org.junit.Test;

public class ReflectionDemo1 {

    //获取对象的三种方式


    @Test
    public void test1() throws ClassNotFoundException {
        //通过对象的 getClass()方法
        Person p = new Person("小明",6);
        Class aClass = p.getClass();

        //通过  类.class
        Class personClass = Person.class;

        //通过  Class.forName()  方法
        Class aClass1 = Class.forName("com.reflection.Person");
    }
}

 

反射常用方法

 

  代码示例

//反射的常用方法
public class ReflectionDemo02 {
 
    /*
        调用无参构造函数创建实例化对象
     */
    @Test
    public void getInstance1(){
        Class<Person> personClass = Person.class;
        try {
            Person person = personClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /*
        调用有参构造函数创建实例化对象
     */
    @Test
    public void getInstance2(){
        Class<Person> personClass = Person.class;
        //获取所有的构造方法
        Constructor<?>[] constructors = personClass.getConstructors();
        for (int i = 0; i < constructors.length; i++) {
            System.out.println(constructors[i].getName());
            System.out.println(constructors[i].getParameterCount());
        }

        //获取指定的构造方法
        try {
            Constructor<Person> constructor = personClass.getConstructor(String.class, int.class);
            Person pp = constructor.newInstance("小明", 6);
            System.out.println(pp);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    //获取类的所有的属性
    @Test
    public void getFields(){
        Class<Person> personClass = Person.class;
        //获取全部 public 修饰的属性
        Field[] fields = personClass.getFields();
        System.out.println(fields.length);
        //获取类中声明的全部属性
        Field[] declaredFields = personClass.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            //获取属性修饰符
            int modifiers = declaredFields[i].getModifiers();
            System.out.println(Modifier.toString(modifiers)+":  "+declaredFields[i].getName());
        }
    }

    //获取类中的 包名、类名称、方法
    @Test
    public void getMethods(){
        Class<Person> personClass = Person.class;
        Person pp = new Person("小明",6);
        //获取包名
        System.out.println(personClass.getPackage());
        //获取全类名
        System.out.println(personClass.getName());
        //获取公有(public)方法,包括继承的方法
        Method[] methods = personClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
            System.out.println(methods[i]);
            if (methods[i].getName().equals("toString")){
                try {
                    //通过 invoke(Object,parameters) 调用方法
                    String s = (String) methods[i].invoke(pp);
                    System.out.println(s);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }

        //获取私有方法,不包括父类继承而来的方法
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            System.out.println(declaredMethods[i]);
            if(declaredMethods[i].getName().equals("set")){
                try {
                    //注意,直接调用私有方法会报异常。需要在调用之前,去除访问修饰符的检查
                    declaredMethods[i].setAccessible(true);
                    Object invoke = declaredMethods[i].invoke(pp);

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }


    }
}

 

  

posted @ 2022-10-18 10:00  藤原豆腐渣渣  阅读(12)  评论(0编辑  收藏  举报