当前位置: 首页 > news >正文

做网站的软件m开头61制作工厂网站

做网站的软件m开头,61制作工厂网站,比较好用的微信社群管理软件,中山市开发区建设局网站✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏:Java从入门到精通 ✨特色专栏&#xff…

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Leo的博客
💞当前专栏:Java从入门到精通
✨特色专栏:MySQL学习
🥭本文内容:反射机制详解
📚个人知识库: Leo知识库,欢迎大家访问

目录

    • 前言
    • 什么是反射
    • 反射的场景
      • 1. 动态对象创建
        • 示例代码:
      • 2. 动态方法调用
        • 示例代码:
      • 3. 访问和修改私有字段
        • 示例代码:
      • 4. 框架和库的实现
        • Spring 示例:
      • 5. 动态代理
        • 示例代码:
    • 反射的基础
    • 认识Class类
    • 认识类加载
      • 类加载机制
      • 类的加载流程
    • 学会使用反射
      • 获取Class对象的几种方式
        • 1. 通过类名(静态方式)
        • 2. 通过对象的 `getClass()` 方法(动态方式)
        • 3. 通过 `Class.forName()` 方法(动态加载)
        • 4. 通过类加载器(ClassLoader)
        • 说明:
      • API基本使用
    • 反射的基本原理

前言

大家好,我是Leo哥🫣🫣🫣,今天一起来回顾一下反射机制。

什么是反射

反射(Reflection) 是编程语言中的一种能力,它允许程序在运行时动态地检查和操作程序元素,比如类、方法、字段等。通俗地说,反射就是程序能够在运行时查看自己并做出相应调整的能力。

如果了解过框架底册的话,那么对反射一定不陌生。

反射之所以被称为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。

假设你有一辆汽车,通常你需要知道汽车的型号、颜色等信息来驾驶它。但如果汽车具备 反射 能力,它自己就能告诉你它的型号、颜色,甚至你可以通过特定的方法直接改变它的某些属性。编程中的反射就是这样一种机制,让程序能够动态地查看和修改自身。

反射的场景

平时大部分时候都是在写业务代码,很少会接触到直接使用反射机制的场景。

但是,这并不代表反射没有用。相反,正是因为反射,你才能这么轻松地使用各种框架。像 Spring、Spring Boot、MyBatis 等等框架中都大量使用了反射机制。

其实反射有许多具体的应用场景的。

反射是一种强大的工具,它允许程序在运行时检查和操作类的结构,包括类的属性、方法和构造函数。反射有许多具体的应用场景,以下是一些常见的应用场景和示例:

1. 动态对象创建

反射可以根据类名在运行时创建对象实例。这对于工厂模式或需要根据配置文件创建实例的场景非常有用。

示例代码:
Class<?> clazz = Class.forName("com.example.MyClass");
Object instance = clazz.getDeclaredConstructor().newInstance();

2. 动态方法调用

反射允许在运行时调用对象的方法,这在需要根据配置或用户输入决定调用哪个方法时特别有用。

示例代码:
Method method = clazz.getMethod("myMethod", String.class);
method.invoke(instance, "Hello");

3. 访问和修改私有字段

反射可以绕过访问控制机制访问和修改私有字段。这对于调试、框架开发和需要操作内部状态的场景非常有用。

示例代码:
Field field = clazz.getDeclaredField("privateField");
field.setAccessible(true);
field.set(instance, "newValue");

4. 框架和库的实现

许多流行的框架和库(如 Spring、Hibernate)使用反射来实现依赖注入、对象关系映射和自动化测试等功能。

Spring 示例:

Spring 使用反射来自动注入依赖项,例如:

@Autowired
private MyService myService;

Spring 在运行时使用反射来查找和注入 MyService 的实例。

5. 动态代理

Java 动态代理机制基于反射,允许在运行时创建接口的代理实例。动态代理常用于 AOP(面向切面编程)和拦截器模式。

示例代码:
InvocationHandler handler = new MyInvocationHandler(targetObject);
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),handler
);

其实注解中也大量使用到了反射机制,例如,我们比较熟悉的Spring框架,我们通过使用一个@Component注解就声明了一个类为 Spring Bean 呢?为什么你通过一个 @Value注解就读取到配置文件中的值呢?

这些都是因为反射机制,获取到类/属性/方法/方法的参数上的注解。你获取到注解之后就可以做进一步处理了。

反射的基础

简单来说,反射就是为把Java类中的各种成分映射成一个个的Java对象。

例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

这里我们首先需要理解 Class类,以及类的加载机制。 然后基于此我们如何通过反射获取Class类以及类中的成员变量、方法、构造方法等。

认识Class类

在 Java 反射中,Class 类是核心部分。它表示正在运行的 Java 应用程序中的类或接口。每个类或接口都有一个与之对应的 Class 对象。当 JVM 加载某个类时,它会创建一个 Class 对象来表示这个类。

Class类,Class类也是一个实实在在的类,存在于JDK的java.lang包中。Class类的实例表示java应用运行时的类(class ans enum)或接口(interface and annotation)(每个Java类运行时都在JVM里表现为一个class对象,可通过类名.class、类型.getClass()、Class.forName(“类名”)等方法获取Class对象)。

image-20240620134343301

通过Class的源码,我们可以得出以下结论:

  • Class类也是类的一种,与class关键字是不一样的。
  • Class<T>类实现了多个接口,包括SerializableGenericDeclarationTypeAnnotatedElement,并且不能被继承(使用了final关键字)。
  • 定义了三个私有静态常量ANNOTATIONENUMSYNTHETIC,分别用于标识注解、枚举和合成类。
  • Class类有一个私有构造函数,只有JVM能够调用,用于初始化Class对象,防止默认构造函数的生成。
  • 私有构造函数通过参数ClassLoader初始化classLoader字段,确保其非空以避免JIT优化问题。

认识类加载

类加载机制

Java类的加载过程包括加载、验证、准备、解析、初始化、使用和卸载七个步骤。加载阶段将类字节码加载到内存中,验证阶段确保类的字节码符合规范,准备阶段为静态变量分配内存,解析阶段将符号引用转换为直接引用,初始化阶段执行类的初始化代码,使用阶段允许类实例化和使用,最后在卸载阶段回收类的内存。

image-20240620134403072

类的加载流程

首先就是编译过程。Java源代码文件(如Person.javaCar.java)被编译成字节码文件(如Person.classCar.class)。

然后就是进入了类加载,类加载器(Class Loader) 负责加载字节码文件。字节码文件可以来自本地文件系统、网络等不同来源。

在方法区中,类加载器将加载的类字节码文件存储到方法区中,并为每个类创建一个对应的数据结构(如Person类数据结构Car类数据结构)。

在堆区中,JVM在堆区中为每个类创建一个唯一的Class对象(如Person Class对象Car Class对象),用于表示该类的元数据。

最后,当程序创建类的实例时(如Person类的实例P1P2等,和Car类的实例C1C2等),这些实例对象在堆区中被分配内存。每个实例对象通过其Class对象获取类的元数据,从而实现反射机制,即可以获取类的内部信息(如方法、属性、构造函数等)以及反向控制实例对象的能力。

通过下面这张图你能更清晰的了解到类加载机制。

image-20240620134425190

学会使用反射

获取Class对象的几种方式

要通过反射获取具体的信息,那么首先需要获取到Class对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。

1. 通过类名(静态方式)

这是获取 Class 对象最常用和最简单的一种方式,适用于在编译时已知类的情况下。

public class MyClass {// 类的定义
}public class Main {public static void main(String[] args) {Class<?> clazz = MyClass.class;System.out.println("Class name: " + clazz.getName());}
}
  • 使用 MyClass.class 可以直接获取 MyClassClass 对象。
  • 这种方式在编译时检查类的存在和合法性,如果类不存在或拼写错误,编译时就会报错。
2. 通过对象的 getClass() 方法(动态方式)

当你已经有一个类的实例对象时,可以通过该对象的 getClass() 方法获取其 Class 对象。

public class MyClass {// 类的定义
}public class Main {public static void main(String[] args) {MyClass obj = new MyClass();Class<?> clazz = obj.getClass();System.out.println("Class name: " + clazz.getName());}
}
  • 使用实例对象的 getClass() 方法可以获取该对象的 Class 对象。
  • 这种方式适用于在运行时已经有类实例的情况下。
3. 通过 Class.forName() 方法(动态加载)

这种方式适用于需要在运行时根据类名字符串动态加载类的场景。

public class Main {public static void main(String[] args) {try {Class<?> clazz = Class.forName("com.example.MyClass");System.out.println("Class name: " + clazz.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
  • 使用 Class.forName("com.example.MyClass") 可以动态加载 MyClass 类。
  • 这种方式适用于在运行时需要根据类名字符串加载类的场景,例如配置文件中指定类名。
4. 通过类加载器(ClassLoader)

这种方式用于需要自定义类加载器的场景,例如在开发插件系统或模块化系统时。

public class Main {public static void main(String[] args) {try {ClassLoader classLoader = Main.class.getClassLoader();Class<?> clazz = classLoader.loadClass("com.example.MyClass");System.out.println("Class name: " + clazz.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
说明:
  • 使用类加载器的 loadClass() 方法可以加载指定类。
  • 这种方式适用于需要自定义类加载逻辑的场景。

API基本使用

image-20240620134535255

image-20240620134602235

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;public class ReflectionExample {public static void main(String[] args) {try {// 获取类的 Class 对象Class<?> clazz = Class.forName("com.example.MyClass");// 获取类名System.out.println("Class Name: " + clazz.getName());// 获取修饰符int modifiers = clazz.getModifiers();System.out.println("Is Public: " + Modifier.isPublic(modifiers));System.out.println("Is Abstract: " + Modifier.isAbstract(modifiers));// 获取父类Class<?> superClass = clazz.getSuperclass();System.out.println("Superclass: " + superClass.getName());// 获取实现的接口Class<?>[] interfaces = clazz.getInterfaces();System.out.println("Interfaces:");for (Class<?> iface : interfaces) {System.out.println(iface.getName());}// 获取字段Field[] fields = clazz.getDeclaredFields();System.out.println("Fields:");for (Field field : fields) {System.out.println(field.getName() + " - " + field.getType().getName());}// 获取方法Method[] methods = clazz.getDeclaredMethods();System.out.println("Methods:");for (Method method : methods) {System.out.println(method.getName() + " - " + method.getReturnType().getName());}// 获取构造函数Constructor<?>[] constructors = clazz.getDeclaredConstructors();System.out.println("Constructors:");for (Constructor<?> constructor : constructors) {System.out.println(constructor.getName());}// 创建实例Constructor<?> constructor = clazz.getConstructor();Object instance = constructor.newInstance();System.out.println("Instance: " + instance);// 调用方法Method method = clazz.getMethod("methodName", String.class);method.invoke(instance, "Hello");// 访问和修改字段Field field = clazz.getDeclaredField("fieldName");field.setAccessible(true);field.set(instance, "newValue");System.out.println("Field Value: " + field.get(instance));} catch (Exception e) {e.printStackTrace();}}
}

反射的基本原理

首先我们编写的 Java 源文件(.java)被保存在磁盘上。然后,这些源文件通过 Java 编译器(javac)编译生成字节码文件(.class)。在编译过程中,编译器会检查源文件中的语法错误,如果存在语法错误,将无法生成字节码文件。接着,JVM 将这些字节码文件加载到内存中。

Java 是面向对象的编程语言,所有事物都可以被看作对象。当字节码文件被加载到内存中时,JVM 会将其表示为一个 Class 对象。这个 Class 对象包含了与类有关的所有信息。

一旦获得了 Class 对象,就可以通过反射机制操作类中的所有内容。Java 将类的成员变量、构造器、成员方法都看作对象,并将其封装到相应的类中。通过 Class 对象,可以调用相应的方法获取类的成员变量对象、构造器对象、成员方法对象。然后,通过这些对象调用方法,就相当于该类在操作自身的属性、构造器和成员方法。这就是反射的基本原理。

每个类在编译后都会生成一个同名的 .class 文件,该文件保存着 Class 对象的内容。类加载实际上是 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用 Class.forName("com.mysql.jdbc.Driver") 这种方式来控制类的加载,该方法会返回一个 Class 对象。反射提供了运行时获取类信息的能力,允许在运行时加载类,即使在编译时期该类的 .class 文件不存在,也可以在运行时加载并使用反射机制操作。

http://www.yayakq.cn/news/275539/

相关文章:

  • 昆山 网站东莞网站制作十强
  • 如何开始做婚恋网站网页设计可以自学吗
  • 国外做游戏的视频网站有哪些问题医院门户网站制作
  • 旅游网站建设实施方案内江做网站哪里便宜
  • 网站seo服务企业宣传软文
  • 一女被多男做的视频网站python做网站用什么软件
  • 网站一键建设建站经验
  • 太子河网站建设做网站属于什么备案
  • html做的网站怎么弄网站基础建设和管理暂行办法
  • 百度网站空间网站建设公司网
  • 广州市外贸网站建设网站子目录怎么做反向代理设置
  • 中国建筑建设通的网站wordpress怎么加js文件路径
  • 西安市网站制作公司可以仿做网站吗
  • 网站正在备案网站开发代淘宝店铺装修
  • 电影网站建设教程下载wordpress英文版下载
  • 商城网站建设企业查询工商营业执照
  • 盘锦市政建设集团网站沈阳网站制作公司哪家好
  • 商业网站备案流程空间购买后打不开网站
  • 无锡惠山区建设局网站如何做解析网站
  • 做网站用最新软件html查看器
  • wordpress找回文章网站优化网络公司
  • 顺企网属于什么网站建网站 就能开店
  • 网站右键禁止类似钉钉的企业管理软件
  • python网站搭建网站开发需求说明书模板
  • 设计网站大全图片动画制作app推荐
  • 国外大型门户网站网站建设前期策划书
  • 安徽省网站建设织梦源码网站模板
  • 网站功能的介绍仓库进销存软件
  • 武隆网站建设报价个人 网站可以做导航吗
  • 安微省建设厅田网站手机排行榜2020前十名