什么是反射机制

反射机制是指java程序在运行时动态加载类并获取类的详细信息 从而操作其属性或者方法,是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

反射原理

反射的实现利用Class类,在Java中万物都是对象,类也不例外,类本身也是对象,每个类别都是Class类别的对象。
一个类别加载后,在方法区域创建代表该类别的Class类别的对象,该对象保存该类别的所有信息,作为访问该类别的入口。
因此,在运行过程中,如果你想通过发射获取某种类型的信息,首先JVM检查该类型是否已经加载,如果没有,首先加载,然后通过调用相应的Class对象获取该类型的信息。

反射的优缺点

优点

  • 增加程序的灵活性,避免将程序写死到代码里。(在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。)
  • 代码简洁,提高代码的复用率,外部调用方便

缺点

  • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射
  • 反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题

获取Class类对象的三种方式

  • 类名.class属性
  • 对象名.getClass()方法
  • Class.forName(全类名)方法
  • 使用类的加载器:ClassLoader
@Test
public void test1() throws ClassNotFoundException {
            //方式一:调用运行时类的属性:.class
            Class clazz1 = Person.class;
            System.out.println(clazz1);//class com.jiaying.java1.Person
            //方式二:通过运行时类的对象,调用getClass()
            Person p1 = new Person();
            Class clazz2 = p1.getClass();
            System.out.println(clazz2);//class com.jiaying.java1.Person

            //方式三:调用Class的静态方法:forName(String classPath)
            Class clazz3 = Class.forName("com.jiaying.java1.Person");
            Class clazz5 = Class.forName("java.lang.String");
            System.out.println(clazz3);//class com.jiaying.java1.Person
            System.out.println(clazz5);//class java.lang.String

            System.out.println(clazz1 == clazz2);//true
            System.out.println(clazz1 == clazz3);//true

            //方式四:使用类的加载器:ClassLoader  (了解)
            ClassLoader classLoader = ReflectionTest.class.getClassLoader();
            Class clazz4 = classLoader.loadClass("com.jiaying.java1.Person");
            System.out.println(clazz4);//class com.jiaying.java1.Person
            System.out.println(clazz1 == clazz4);//true
}

反射获取构造方法并应用

package com.fanshe;

import java.lang.reflect.Constructor;

public class Student {
    private String name;
    private int age;

    // 私有的有参构造方法
    private Student(String name) {
        System.out.println("name的值为:" + name);
        System.out.println("private...Student的有参构造方法");
    }

    // 公共的无参构造方法
    public Student() {
        System.out.println("public...Student的无参构造方法");
    }

    // 公共的有参构造方法
    public Student(String name, int age) {
        System.out.println("name的值为:" + name + "age的值为:" + age);
        System.out.println("public...Student的有参构造方法");
    }
}


class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        System.out.println("获取所有公共构造方法对象的数组===========");
        method1();
        System.out.println("获取单个构造方法对象===========");
        method2();
        System.out.println("获取所有构造方法对象的数组===========");
        method3();
        System.out.println("获取单个构造方法对象===========");
        method4();
    }

    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        //        Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):
        //                                      返回单个构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        System.out.println("String+int的构造");
        Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class);

        System.out.println(constructor);
        System.out.println("String的构造");
        constructor=clazz.getDeclaredConstructor(String.class);
        System.out.println(constructor);

    }

    private static void method3() throws ClassNotFoundException, NoSuchMethodException {
        //        Constructor<T> getConstructor(Class<?>... parameterTypes):
        //                                      返回单个公共构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //小括号中,一定要跟构造方法的形参保持一致.
        Constructor constructor1 = clazz.getConstructor();
        System.out.println(constructor1);

        Constructor constructor2 = clazz.getConstructor(String.class, int.class);
        System.out.println(constructor2);

        //因为Student类中,没有只有一个int的构造,所以这里会报错.
//        Constructor constructor3 = clazz.getConstructor(int.class);
//        System.out.println(constructor3);
    }

    private static void method2() throws ClassNotFoundException {
        //        Constructor<?>[] getDeclaredConstructors():
        //                                      返回所有构造方法对象的数组
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");

        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }

    private static void method1() throws ClassNotFoundException {
        //        Constructor<?>[] getConstructors():
        //                                      返回所有公共构造方法对象的数组
        //1.获取Class对象
        Class clazz = Class.forName("com.fanshe.Student");
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
    }
}

Constructor类用于创建对象的方法

package com.fanshe;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Student {
    private String name;
    private int age;

    // 私有的有参构造方法
    private Student(String name) {
        System.out.println("name的值为:" + name);
        System.out.println("private...Student的有参构造方法");
    }

    // 公共的无参构造方法
    public Student() {
        System.out.println("public...Student的无参构造方法");
    }

    // 公共的有参构造方法
    public Student(String name, int age) {
        System.out.println("name的值为:" + name + "age的值为:" + age);
        System.out.println("public...Student的有参构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


// T newInstance(Object... initargs):根据指定的构造方法创建对象
class ReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        
        method1();
        method2();
        method3();
        method4();
    }

    private static void method4() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //获取一个私有的构造方法并创建对象
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取一个私有化的构造方法.
        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //被private修饰的成员,不能直接使用的
        //如果用反射强行获取并使用,需要临时取消访问检查
        constructor.setAccessible(true);

        //3.直接创建对象
        Student student = (Student) constructor.newInstance("zhangsan");

        System.out.println(student);
    }

    private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //简写格式
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
        Student student = (Student) clazz.newInstance();//这个方法现在已经过时了,了解一下

        System.out.println(student);
    }

    private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取构造方法对象
        Constructor constructor = clazz.getConstructor();

        //3.利用空参来创建Student的对象
        Student student = (Student) constructor.newInstance();

        System.out.println(student);
    }

    private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, InvocationTargetException {
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取构造方法对象
        Constructor constructor = clazz.getConstructor(String.class, int.class);

        //3.利用newInstance创建Student的对象
        Student student = (Student) constructor.newInstance("杨天真", 22);

        System.out.println(student);
    }
}

小结

如果是public的,直接创建对象

newInstance(Object... initargs)

如果是非public的,需要临时取消检查,然后再创建对象

setAccessible(boolean)  暴力反射

反射获取成员变量并使用

package com.fanshe;

import java.lang.reflect.Field;

public class Student {

    public String name;
    public int age;
    public String gender;
    private int money = 300;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", money=" + money +
                '}';
    }
}

class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        method1();
        method2();
        method3();
        method4();
    }

    private static void method4() throws ClassNotFoundException, NoSuchFieldException {
        //        Field getDeclaredField(String name):返回单个成员变量对象
        System.out.println("返回单个成员变量对象==================");

        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取money成员变量
        Field field = clazz.getDeclaredField("money");

        //3.打印一下
        System.out.println(field);
    }

    private static void method3() throws ClassNotFoundException, NoSuchFieldException {
        //        Field getField(String name):返回单个公共成员变量对象
        System.out.println("返回单个公共成员变量对象==================");

        //想要获取的成员变量必须是真实存在的
        //且必须是public修饰的.
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取name这个成员变量
        Field field = clazz.getField("name");

        //3.打印一下
        System.out.println(field);
    }

    private static void method2() throws ClassNotFoundException {
        //        Field[] getDeclaredFields():返回所有成员变量对象的数组
        System.out.println("返回所有成员变量对象的数组==================");

        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取所有的Field对象
        Field[] fields = clazz.getDeclaredFields();

        //3.遍历
        for (Field field : fields) {
            System.out.println(field);
        }
    }

    private static void method1() throws ClassNotFoundException {
        //        Field[] getFields():返回所有公共成员变量对象的数组
        System.out.println("返回所有公共成员变量对象的数组==================");
        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");

        //2.获取Field对象.
        Field[] fields = clazz.getFields();

        //3.遍历
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

Method类用于执行方法的方法

package com.fanshe;

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

public class Student {

    //私有的,无参无返回值
    private void show() {
        System.out.println("私有的show方法,无参无返回值");
    }

    //公共的,无参无返回值
    public void function1() {
        System.out.println("function1方法,无参无返回值");
    }

    //公共的,有参无返回值
    public void function2(String name) {
        System.out.println("function2方法,有参无返回值,参数为" + name);
    }

    //公共的,无参有返回值
    public String function3() {
        System.out.println("function3方法,无参有返回值");
        return "aaa";
    }

    //公共的,有参有返回值
    public String function4(String name) {
        System.out.println("function4方法,有参有返回值,参数为" + name);
        return "bbb";
    }
}

class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, InvocationTargetException {
//        Object invoke(Object obj, Object... args):运行方法
//        参数一:用obj对象调用该方法
//        参数二:调用方法的传递的参数(如果没有就不写)
//        返回值:方法的返回值(如果没有就不写)

        //1.获取class对象
        Class clazz = Class.forName("com.fanshe.Student");
        //2.获取里面的Method对象  function4
        Method method = clazz.getMethod("function4", String.class);
        //3.运行function4方法就可以了
        //3.1创建一个Student对象,当做方法的调用者
        Student student = (Student) clazz.newInstance();
        //3.2运行方法
        Object result = method.invoke(student, "杨天真");
        //4.打印一下返回值
        System.out.println(result);
    }
}

好啦看到这里 你学会了吗

或许不是我们变了 而是我们越来越接近真实的自己