【反射】获取类、构造器、成员变量、成员方法以及作用和应用场景

反射

1.认识反射、获取类
  • 反射(Reflection):加载类,并允许以编程的方式,解剖类中各种成分(成员变量、方法、构造器等)

  • 获取Class对象的三种方式

    (1)Class对象阶段(已经加载到内存)->Class c1=类名.class

    (2)源码阶段(还没有加载到内存)->调用Class提供的方法:public static Class forName(String package)

    (3)Runtime运行阶段(手动new对象时)->Object提供的方法:public Class getClass(); Class c3=对象.getClass()

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、Class类的静态方法forName(String 全限定名);
        Class c1 = Class.forName("com.demo04_reflect_获取类.Student");//全类名=包名+类名
        System.out.println(c1.getName()); //com.demo04_reflect_获取类.Student
        System.out.println(c1.getSimpleName()); //Student

        //2、类名.class
        Class c2 = Student.class;
        System.out.println(c2.getName());
        System.out.println(c2.getSimpleName());

        //3、对象.getClass()
        Student stu = new Student("张三", 18);
        Class c3 = stu.getClass();
        System.out.println(c3.getName());
        System.out.println(c3.getSimpleName());

        //这三个Class对象是不是一个对象?
        System.out.println(c1 == c2);//true
        System.out.println(c2 == c3);//true
    }
}
2.获取类的构造器
  • Class提供了从类中获取构造器的方法

    方法 说明
    Constructor[] getConstructors() 获取全部构造器(只能获取public修饰的)
    Constructor[] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)
    Constructor< T >[] getConstructors(Class… parameterTypes) 获取某个构造器(只能获取public修饰的)
    Constructor< T >[] getDeclaredConstructors(Class… parameterTypes) 获取某个构造器(只要存在就能拿到)
  • 获取类构造器的作用:依然是初始化对象返回

    Constructor提供的方法 说明
    T newInstance(Object…initargs) 调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

    实体类Cat:

    public class Cat {
        //公共空参
        public Cat() {
        }
    
        //公共带参
        public Cat(String name, int age) {
        }
    
        //私有带参
        private Cat(String name) {
        }
    }
    

    测试类:

    public class Demo {
        @Test
        public void testGetDeclaredConstructor() throws NoSuchMethodException {
            //加载类
            Class clazz = Cat.class;
            //获取单个指定的(只要存在,包含私有
            Constructor c1 = clazz.getDeclaredConstructor(String.class);
            System.out.println(c1); //private com.demo05_reflect_获取构造器对象.Cat(java.lang.String)
        }
    
        @Test
        public void testGetConstructor() throws NoSuchMethodException {
            Class clazz = Cat.class;
            //获取单个指定的(公共的)
            Constructor c1 = clazz.getConstructor();
            System.out.println(c1); //public com.demo05_reflect_获取构造器对象.Cat()
            Constructor c2 = clazz.getConstructor(String.class, int.class);
            System.out.println(c2); //public com.demo05_reflect_获取构造器对象.Cat(java.lang.String,int)
        }
    
        @Test
        public void testGetDeclaredConstructors() {
            Class clazz = Cat.class;
            //Constructor[] getDeclaredConstructors(); 获取所有(只要存在,包含私有的)
            Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
            //遍历数组
            for (Constructor declaredConstructor : declaredConstructors) {
                System.out.println(declaredConstructor);
                /*
                    public com.demo05_reflect_获取构造器对象.Cat()
                    public com.demo05_reflect_获取构造器对象.Cat(java.lang.String,int)
                    private com.demo05_reflect_获取构造器对象.Cat(java.lang.String)
                 */
            }
        }
    
        @Test
        public void testGetConstructors() {
            Class clazz = Cat.class;
            //Constructor[] getConstructors(); 获取所有(公共的)
            Constructor[] constructors = clazz.getConstructors();
            //遍历数组
            for (Constructor constructor : constructors) {
                System.out.println(constructor);
                /*
                    public com.demo05_reflect_获取构造器对象.Cat()
                    public com.demo05_reflect_获取构造器对象.Cat(java.lang.String,int)
                 */
            }
        }
    }
    

    通过构造器实例化对象

    实体类Cat:

    public class Cat {
        private String name;
        private int age;
    
        //私有空参
        private Cat() {
            System.out.println("私有空参执行了...");
        }
    
        //公共带参
        public Cat(String name, int age) {
            System.out.println("公共带参执行了...");
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Cat{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

    测试类:

    public class Demo {
        @Test //通过公共带参,创建对象
        public void testNewInstance2() throws Exception {
            //加载类
            Class clazz = Cat.class;
            //获取公共的带构造
            Constructor constructor = clazz.getConstructor(String.class, int.class);
            //T newInstance(参数1,参数2..); 通过构造器对象和指定参数,创建对象并返回(可强转为具体类型)
            Cat cat = (Cat) constructor.newInstance("大橘", 5);
            System.out.println(cat); //Cat{name='大橘', age=5}
        }
    
        @Test //通过私有空参,创建对象
        public void testNewInstance1() throws Exception {
            //加载类
            Class clazz = Cat.class;
            //获取私有的空参构造
            Constructor constructor = clazz.getDeclaredConstructor();
            //public void setAccessible(boolean flag); 参数为true表示禁止检查访问控制(暴力反射)
            constructor.setAccessible(true); //禁止检查
            //T newInstance(参数1,参数2..); 通过构造器对象和指定参数,创建对象并返回(可强转为具体类型)
            Cat c = (Cat) constructor.newInstance();
            System.out.println(c); //Cat{name='null', age=0}
        }
    }
    
3.获取类的成员变量
  • Class提供了从类中获取成员变量的方法

    方法 说明
    public Filed[] getFileds() 获取类的全部成员变量(只能获取public修饰的)
    public Filed[] getDeclaredFileds() 获取类的全部成员变量(只要存在就能拿到)
    public Filed getFiled(String name) 获取类的某个成员变量(只能获取public修饰的)
    public Filed[] getDeclaredFiled(String name) 获取类的某个成员变量(只要存在就能拿到)
  • 获取到成员变量的作用:依然是赋值、取值

    方法 说明
    void set(Object obj,Object value) 赋值
    Object get(Object obj) 取值
    public void seAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
    class Cat {
        public static int number;
        public static final String COUNTRY = "中国";
        private String name;
        private int age;
    
        public Cat() {
    
        }
    
        public Cat(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Cat{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    public class Demo {
        //给成员变量赋值和取值
        @Test
        public void testGetAndSet() throws Exception {
            Class clazz = Cat.class;
            Field field = clazz.getDeclaredField("name");
            field.setAccessible(true);
            Cat c = new Cat();
            String name = (String)field.get(c);
            //System.out.println(name);
            field.set(c,"daju");
            String name1=(String)field.get(c);
            System.out.println(name1);
    
        }
    
        @Test
        public void testGetDeclaredField() throws NoSuchFieldException {
            Class clazz = Cat.class;
            System.out.println(clazz.getDeclaredField("name"));
    
        }
    
        @Test
        public void testGetField() throws NoSuchFieldException {
            Class clazz = Cat.class;
            System.out.println(clazz.getField("number"));
    
    
        }
    
        @Test
        public void testGetDeclaredFields() {
            Class clazz = Cat.class;
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println(declaredField);
    
            }
    
        }
    
        @Test
        public void testGetFields() {
            Class clazz = Cat.class;
            Field[] fields = clazz.getFields();
            for (Field field : fields) {
                System.out.println(field);
    
            }
    
        }
    }
    
4.获取类的成员方法
  • Class提供了从类中获取成员方法的API

    方法 说明
    Method[] getMethods() 获取类的全部成员方法(只能获取public修饰的)
    Method getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name,Class…parameterTypes) 获取类的某个成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name,Class…parameterTypes) 获取类的某个成员方法(只要存在就能拿到)
  • 成员方法的作用:依然是执行

    Method提供的方法 说明
    public Object invoke(Object obj,Object…args) 触发某个对象的方法执行
    public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
class Cat {
    private String name;
    private int age;

    public Cat() {

    }

    public Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //公共,无参无返
    public void play() {
        System.out.println("小猫捉迷藏");
    }

    //私有,有参有返
    private String eat(String food) {
        return "小猫爱吃" + food;
    }

    //公共,无参有返
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo {

    @Test
    public void testGetDeclaredMethod() throws Exception {
        Class clazz = Cat.class;
        Method declaredMethod = clazz.getDeclaredMethod("eat", String.class);
        Cat c = (Cat)clazz.newInstance();
        declaredMethod.setAccessible(true);
        Object invoke = declaredMethod.invoke(c, "maotiao");
        System.out.println(invoke);


    }

    @Test
    public void testGetMethod() throws Exception{
        Class clazz = Cat.class;
        Method method = clazz.getMethod("play");
        Cat c = (Cat) clazz.newInstance();
        method.invoke(c);

    }

    @Test
    public void testGetDeclaredMethods() throws Exception {
        Class clazz = Cat.class;
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());

        }

    }

    @Test
    public void testGetMethods() {
        Class clazz = Cat.class;
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());

        }
    }
}
5.作用、应用场景
  • 基本作用:可以得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 最重要的用途:适合做Java的框架,基本上主流的框架都会基于反射设计出一些通用的功能

你可能感兴趣的:(java,开发语言)