举例体会反射的动态性

首先要知道我们这里所说的动态性指的是什么

动态性就是编译期间不确定,而在运行期间才确定的特性

  • 如果在编译期间就确定了,那么我们就称之为静态
  • 所以这里我们要体现动态性,那么也就是编译期间要求不确定,而在运行期间才确定
这里我们通过一个例子来理解反射的动态性
package 反射.反射的动态性;

import java.util.Random;

public class Demo {
    /*
    这个方法的作用就是创建一个全类名为classPath的类的对象,但是我们的classPath到底指的是哪个类,这个我们在编译期间并不能确定
    只有在运行期间,等num给定之后我们才能确定创建的是哪个类的对象
    
    通过这种方法我们就体现出了反射的动态性,也就是编译期间不确定,等到运行期间才进行确定
     */
    public static void main(String[] args) {
        int num = new Random().nextInt(3);
        String classPath = "";
        switch(num){
            case 0: classPath = "java.util.Date";
            break;
            case 1: classPath = "java.lang.Object";
            break;
            //这里的反射.反射的动态性.Person是我们的一个指定路径下的自定义类
            case 2: classPath = "反射.反射的动态性.Person";
            break;
        }
        try{
            Object obj = getInstance(classPath);
            System.out.println(obj);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    //这个方法时我们用来创建某个类的实例的方法,我们提供一个全类名,这个方法就会创建一个给定类的对象
    public static Object getInstance(String classPath)throws ClassNotFoundException,InstantiationException,IllegalAccessException{
        /*
        我们获取Class类的实例的方式前面讲了四种:
        1. 通过某个类调用class属性
        2. 通过某个类的对象调用getClass()方法
        3. 通过调用Class类中的静态方法forName(String classPath)方法
        4. 通过使用某个类加载器对象调用loadCLass(String classPath)方法
        注意: 我们也说了,我们最常用的,也是最能更好的体现发射的动态性的是第三种,也就是通过Class类中的静态方法forName(String classPath)
         */
        Class clazz = Class.forName(classPath);
        //newInstance()方法底层调用了对应运行时类的无参构造方法
        return clazz.newInstance();
    }
}

总结:

我们的这个例子中编译期间可以看出来要创建一个全类名为classPath的类的对象,这个classPath是一个String类型的变量,这个变量在编译期间并不能确定,只知道classPath是 java.util.Date , java.lang.Object , 自定义Person类中的一个,具体是要创建哪一个类的对象只有在运行期间执行了Random类中的nextInt()方法,得到一个int类型的值之后执行了switch语句之后才可以确定 - --> 那么也就是说编译期间确定不了,只有在运行期间才可以确定 ,从而也就体现了反射的动态性

补充:

在我们后面学习到java框架的时候我们会大量的使用到反射, 因为框架就是一种通用的编程,我们利用反射就可以很好地完成这种通用编程

  • 框架 = “注解 + 反射 + 设计模式”