星海问道 星海问道
首页
后端技术
框架和工具
工程实践
成长感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

pohongying

后端开发工程师
首页
后端技术
框架和工具
工程实践
成长感悟
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaSE基础

    • Java反射机制
      • 一、Java反射机制概述
        • 1.1 反射机制简介
        • 1.2 反射机制的应用场景
      • 二、Java反射机制的创建模式和常用方法
        • 2.1 获取Class对象的三种方式
        • 2.2 获取类的构造器
        • 2.3 获取类的成员变量
        • 2.4 获取类的方法
      • 三、Java反射机制的源码分析
        • 3.1 Class.forName()方法的源码分析
        • 3.2 Constructor.newInstance()方法的源码分析
        • 3.3 Method.invoke()方法的源码分析
  • JUC并发

  • JVM

  • 计算机理论

  • 数据结构

  • 数据库

  • 后端开发
  • JavaSE基础
pohongying
2024-03-20
目录

Java反射机制

# 一、Java反射机制概述

# 1.1 反射机制简介

Java反射机制是Java语言中一个非常强大的特性,它允许程序在运行时动态地访问和修改类的属性、方法、构造函数等信息。通过反射,我们可以在运行时创建对象、调用方法、获取和设置字段值等,极大地提高了程序的灵活性和可扩展性。

# 1.2 反射机制的应用场景

  • 框架设计:许多Java框架(如Spring、Hibernate等)都大量使用了反射机制,以实现依赖注入、对象关系映射等功能。
  • 动态代理:Java的动态代理机制(如JDK动态代理)也是基于反射实现的。
  • 配置文件驱动:在一些应用中,可以通过配置文件来指定类名和方法名,然后在程序运行时通过反射动态地加载和调用这些类和方法。

# 二、Java反射机制的创建模式和常用方法

# 2.1 获取Class对象的三种方式

要使用反射机制,首先需要获取到代表类的Class对象。Java提供了三种获取Class对象的方式:

  • 通过对象的getClass()方法:这种方式需要先创建一个类的对象,然后调用对象的getClass()方法来获取Class对象。例如:

    Student student = new Student();
    Class stuClass = student.getClass();
    
    1
    2
  • 通过类名的.class属性:这种方式直接通过类名的.class属性来获取Class对象,是获取Class对象最简单的方式之一。例如:

    Class stuClass = Student.class;
    
    1
  • 通过Class类的forName()方法:这种方式通过Class类的静态方法forName()来获取Class对象,需要传入类的全限定名作为参数。例如:

    Class stuClass = Class.forName("fanshe.Student");
    
    1

    这种方式是最为常见和灵活的,因为它可以在运行时动态地加载指定的类。

# 2.2 获取类的构造器

通过Class对象,我们可以获取到类的构造器,从而在运行时创建类的对象。获取构造器的方法主要有以下几种:

  • getDeclaredConstructors():返回类中所有构造器的数组,包括私有的构造器。

    Constructor[] constructors = stuClass.getDeclaredConstructors();
    
    1
  • getConstructors():返回类中所有公共构造器的数组。

    Constructor[] constructors = stuClass.getConstructors();
    
    1
  • getConstructor(Class<?>... parameterTypes):返回类中指定参数类型的公共构造器。

    Constructor constructor = stuClass.getConstructor(String.class);
    
    1
  • getDeclaredConstructor(Class<?>... parameterTypes):返回类中指定参数类型的构造器,包括私有的构造器。

    Constructor constructor = stuClass.getDeclaredConstructor(String.class);
    
    1

    获取到构造器后,可以通过调用构造器的newInstance()方法来创建类的对象。例如:

    Student student = (Student) constructor.newInstance("张三");
    
    1

# 2.3 获取类的成员变量

通过Class对象,我们还可以获取到类的成员变量,并对其进行操作。获取成员变量的方法主要有以下几种:

  • getFields():返回类中所有公共成员变量的数组。

    Field[] fields = stuClass.getFields();
    
    1
  • getDeclaredFields():返回类中所有成员变量的数组,包括私有的成员变量。

    Field[] fields = stuClass.getDeclaredFields();
    
    1
  • getField(String name):返回类中指定名称的公共成员变量。

    Field field = stuClass.getField("name");
    
    1
  • getDeclaredField(String name):返回类中指定名称的成员变量,包括私有的成员变量。

    Field field = stuClass.getDeclaredField("age");
    
    1

    获取到成员变量后,可以通过调用成员变量的get()和set()方法来获取和设置成员变量的值。例如:

    Object value = field.get(student);
    field.set(student, "李四");
    
    1
    2

# 2.4 获取类的方法

通过Class对象,我们可以获取到类的方法,并在运行时调用这些方法。获取方法的方法主要有以下几种:

  • getMethods():返回类中所有公共方法的数组,包括继承自父类的方法。

    Method[] methods = stuClass.getMethods();
    
    1
  • getDeclaredMethods():返回类中所有方法的数组,包括私有的方法。

    Method[] methods = stuClass.getDeclaredMethods();
    
    1
  • getMethod(String name, Class<?>... parameterTypes):返回类中指定名称和参数类型的公共方法。

    Method method = stuClass.getMethod("study", String.class);
    
    1
  • getDeclaredMethod(String name, Class<?>... parameterTypes):返回类中指定名称和参数类型的方法,包括私有的方法。

    Method method = stuClass.getDeclaredMethod("eat", String.class);
    
    1

    获取到方法后,可以通过调用方法的invoke()方法来执行该方法。例如:

    method.invoke(student, "Java");
    
    1

# 三、Java反射机制的源码分析

# 3.1 Class.forName()方法的源码分析

Class.forName()方法是获取Class对象最常用的方式之一,其源码实现主要分为以下几个步骤:

  • 获取调用者的类加载器:通过Reflection.getCallerClass()方法获取调用者的类信息,从而获取当前的类加载器。
  • 调用native方法获取类信息:调用forName0()方法,该方法是一个native方法,由JVM实现,用于获取类的字节码信息。
  • 加载类:通过调用ClassLoader的loadClass()方法来加载类。loadClass()方法会先检查类是否已经被加载,如果已经被加载,则直接返回;否则,会调用findClass()方法来查找并加载类。

# 3.2 Constructor.newInstance()方法的源码分析

Constructor.newInstance()方法用于通过构造器创建类的对象,其源码实现主要分为以下几个步骤:

  • 权限检测:检查是否有权限调用该构造器,如果没有权限,则抛出异常。
  • 查找无参构造器:通过getConstructor0()方法查找类的无参构造器,并将其缓存起来。
  • 调用无参构造器:通过调用ConstructorAccessor的newInstance()方法来调用无参构造器,从而创建类的对象。

# 3.3 Method.invoke()方法的源码分析

Method.invoke()方法用于调用类的方法,其源码实现主要分为以下几个步骤:

  • 权限检测:检查是否有权限调用该方法,如果没有权限,则抛出异常。
  • 获取MethodAccessor:通过acquireMethodAccessor()方法获取MethodAccessor对象,该对象用于执行方法调用。
  • 执行方法调用:通过MethodAccessor的invoke()方法来执行方法调用。在第一次调用时,会生成一个代理Accessor来执行方法调用,后续调用则直接使用生成的Accessor。
编辑 (opens new window)
#反射
juc介绍

juc介绍→

最近更新
01
juc介绍
02-18
02
Git配置
02-18
03
计算机网络基础
03-20
更多文章>
Theme by Vdoing | Copyright © 2025-2025 pohongying | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式