Java--反射

yangcurry / 2024-08-30 / 原文

目录
  • 类加载机制
  • 什么是反射
  • 反射的原理
        • 传统静态加载类
        • 反射动态加载类
  • class对象
      • 三种获取class对象方式
        • 类对象示例的getClass()方法
        • 任何数据类型的静态class属性
        • Class.forName()方法
      • 两种创建对象方式
        • 默认的构造器通过Class的newInstance()方法来获取
        • 指定的构造器来创建
  • 反射的优点和缺点
        • Java反射的优点
        • Java反射的缺点
  • 反射的用途

类加载机制

负责读取 Java 字节代码,并转换成java.lang.Class类的一个实例;

类加载七个步骤:加载,验证,准备,解析,初始化,使用,卸载

类加载器:启动类加载器,扩展类加载器,应用类加载器(程序员)

什么是反射

Java 反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法(本质是 JM 得到 Class 对象之后,再通过 Class 对象进行反编译,从而获取对象的各种信息)

Java 属于先编译再运行的语言,对象类型在编译期确定

当程序在运行时可能需要动态加载某些类,通过反射可以在运行时动态地创建对象并调用其属性,不需要提前在编译期确定对象类型

反射的原理

传统静态加载类

Person person = newPerson();编译时已确定对象类型,程序运行时通过类加载器加载 Person 类并创建该类的 Class 对象

反射动态加载类

Class object = Class.forName(" Person ");编译时未确定对象类型,程序运行时通过类加载器无法加载 Person 类只有到执行以上代码时,类加载器才知道对象类型,这时才开始加载Person 类,创建该类的 Class 对象,并返回给 object 变量

class对象

每个类在 JVM 中都有一个与之相关的 Class 对象,是类加载器创建的特殊对象不是类的实例化对象

Class object = Class.forName(" Person ");Person person=(Person)object.newInstance( );

反射通过获得的 Class 对象就可以得到类的元信息,调用 newInstance()方法就是通过类的元信息来动态创建 Person 对象实例

三种获取class对象方式

类对象示例的getClass()方法
Student student = new Student();

Class object = student.getClass();
任何数据类型的静态class属性

Class object = Student.class;

Class.forName()方法
Class object = Class.forName("Student");
Class<?> clazz =Class.forName("java.long.String");

两种创建对象方式

反射动态创建对象

默认的构造器通过Class的newInstance()方法来获取
指定的构造器来创建
import java.lang.reflect.Constructor;
public class ReflectDemo2 {
   public static void main(String[] args) throws Exception {
       /*
        如何根据给定名称获取到指定的Class对象后建立该类的对象呢? 
        getObject_1(); 通过默认构造器new对象        
        getObject_2(); 通过指定构造器new对象*/
        
    }
    public static void getObject_2() throws Exception {
        String className = "cn.qujianlei.domain.Person";
        Class clazz = Class.forName(className);
        /*
         * 万一给定类中没有空参数的构造方法呢?
         * 可以先获取指定的构造方法,再通过该构造方法进行实例化
         */ 
        //1.通过Class获取指定构造方法,比如带两个参数
        Constructor cons=clazz.getConstructor(String.class,int.class);//拿的是公有的
        
//        System.out.println(cons);
        
        //2.通过指定的构造器对象进行对象的初始化。
        Object obj = cons.newInstance("lisisi",23);
    }

    public static void getObject_1() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //1.根据给定的类名获取Class对象
        String className = "cn.qujianlei.domain.Person";
        Class clazz = Class.forName(className);
        Object obj = clazz.newInstance();//创建了一个Person对象,默认调用该类的空参数构造方法
        //记住:一般被反射的类通常都有空参数的构造方法。
        //java.lang.InstantiationException  没有调用到与之对应的构造方法
    }
}

反射的优点和缺点

Java反射的优点

增加程序的灵活性,可以在程序运行过程中动态的对类进行修改和操作。
提高代码的复用率,比如动态代理,就是利用了反射来实现。
可以在运行时轻松获取任意一个类的方法、属性,并且还能通过反射进行动态调用。

Java反射的缺点

反射会涉及动态类型的解析,所以JVM无法对这些代码进行优化,导致性能要比非反射调用更低。
使用反射后,代码的可读性会下降
反射可以绕过一些限制访问属性或者方法,可能会破坏了代码本身的抽象性

反射的用途

开发各种通用框架

1.各种框架:(spring,struts....)用反射,运行时动态加载需要加载的对象。

2.各种IDE开发工具:当我们输入一个对象或类并想调用它的属性或方法时,一按点号,编译器就会自动列出它的属性或方法,这里就会用到反射。