第9章-第2节-Java中的反射机制

1、概念:

反射机制:是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意属性和方法;这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制;

他的工作原理是这样的:当一个字节码文件加载到内存的时候, jvm会对该字节码进行解剖,然后创建一个对象的Class对象,jvm把字节码文件的信息全部都存储到该Class对象中,我们只要获取到Class对象,我们就可以使用该对象设置对象的属性或者调用对象的方法等操作。

2、获取Class类对象的三种方式

* 类名.class属性
* 对象名.getClass()方法
* Class.forName(全类名)方法 

3、原理图:

第9章-第2节-Java中的反射机制_第1张图片

4、案例:获得Class类

class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1.Class类中的静态方法forName("全类名")
        //全类名:包名 - 类名
        Class clazz1 = Class.forName("com.bean.Student");
        System.out.println(clazz1);

        // 2.通过class属性来获取
        Class clazz2 = Student.class;
        System.out.println(clazz2);

        // 3.利用对象的getClass方法来获取class对象
        // getClass方法是定义在Object类中.
        Student s = new Student();
        Class clazz3 = s.getClass();
        System.out.println(clazz3);


        System.out.println(clazz1 == clazz2);
        System.out.println(clazz2 == clazz3);
    }
}

 5、获得构造方法,还可以获得成员属性Field、成员方法Method等这些,获得私有的时用带上Declared的方法,例如:getDeclaredConstructor

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 getDeclaredConstructor(Class... parameterTypes):
        //返回单个构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.bean.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 getConstructor(Class... parameterTypes):
        // 返回单个公共构造方法对象
        //1.获取Class对象
        Class clazz = Class.forName("com.bean.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 {
        //返回所有构造方法对象的数组
        //1.获取Class对象
        Class clazz = Class.forName("com.bean.Student");

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

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

 6、通过构造方法创建对象

方法名 说明
T newInstance(Object…initargs) 根据指定的构造方法创建对象
setAccessible(boolean flag) 设置为true,表示取消访问检查
// 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.bean.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.bean.Student");

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

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

        System.out.println(student);
    }
}

 7、反射和new 的区别

1)、new的对象无法访问其中的私有属性,反射出来的可以通过设置setAccessible()方法来省略访问权限符;

2)、new必须要知道类名,而反射创建对象不需要知道类型也可以创建;

本电子书目录:《Java基础的重点知识点全集》

你可能感兴趣的:(java)