带你深入学习“反射”技术

简介: 带你深入学习“反射”技术

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌
Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕

文章目录
• 1、什么是动态语言,什么是静态语言
• 2、什么是反射
• 3、Java 获取 Class 对象的几种方式
• 4、如何通过反射获取 Java 实例
• 5、反射有什么优缺点
• 6、反射的应用场景
• 7、反射的几个重要的 API
• 8、什么是“反射爆破”

1、什么是动态语言,什么是静态语言
动态语言和静态语言是编程语言的两种基本类型。
静态语言是指在编译时就已经确定变量的数据类型,一旦确定就不能修改。程序在编译时会进行类型检查,如果存在类型不匹配的情况,编译器会报错。常见的静态语言包括Java、C、C++等。
动态语言是指在运行时才确定变量的数据类型,变量的类型可以随时改变。程序在运行时会进行类型检查,如果存在类型不匹配的情况,程序会抛出异常。常见的动态语言包括Python、JavaScript、Ruby等。
相比而言,静态语言在编译时就能发现类型错误,避免了一些常见的错误,但是编写起来比较繁琐。而动态语言则更加灵活,编写起来比较简单,但是容易出现类型错误。不同的编程语言都有自己的优缺点,开发者可以根据实际需求选择合适的语言。
2、什么是反射
反射是动态语言的关键,更是Java语言的一个重要特性,它允许程序在运行时动态地获取类的信息并操作对象。通过反射,程序可以在运行时获取类的构造器、方法、字段等信息,并且可以动态地创建对象、调用方法、修改字段等操作。反射在Java中的应用非常广泛,比如在框架、动态代理、注解、序列化等方面都有重要的作用。但是反射也存在一定的性能问题,因为它需要在运行时进行动态的类型检查和方法调用,所以会带来一定的性能损失。因此,在使用反射时需要谨慎考虑性能问题,避免滥用反射导致程序性能下降。
下面是一个类获取实例的正常方式和反射方式,反射方式就是和正常方式反着来。
3、Java 获取 Class 对象的几种方式
在Java中,获取Class对象的几种方式有以下几种:

  1. 使用Class.forName()方法:该方法可以根据类的全限定名获取该类的Class对象,例如: ​​Class clazz = Class.forName("com.example.Person");​​
  2. 使用类的class属性:每个类都有一个class属性,可以直接通过类名.class获取该类的Class对象,例如: ​​Class clazz = Person.class;​​
  3. 使用对象的getClass()方法:每个对象都有一个getClass()方法,可以获取该对象的Class对象,例如: ​​Person person = new Person(); Class clazz = person.getClass();​​
  4. 使用ClassLoader的loadClass()方法:ClassLoader可以动态加载类,可以通过ClassLoader的loadClass()方法获取该类的Class对象,例如: ​​ClassLoader classLoader = ClassLoader.getSystemClassLoader(); Class clazz = classLoader.loadClass("com.example.Person");​​
  5. (特殊) 基本类型的封装类Type可以获得 ​​Class intclass = Integer .TYPE​​
    以上是获取Class对象的几种常见方式,开发者可以根据实际需求选择合适的方式获取Class对象。
    4、如何通过反射获取 Java 实例
    下面是一段通过反射的获取实例的案例:
    package com.pany.camp.reflect;

import java.lang.reflect.Method;

/*

  • @description: 反射
  • @copyright: @Copyright (c) 2022
  • @company: Aiocloud
  • @author: pany
  • @version: 1.0.0
  • @createTime: 2023-06-26 8:29
    */
    public class ReflectExample {
    public static void main(String[] args) {
     try {
         // 获取类的Class对象
         Class<?> clazz = Class.forName("com.pany.camp.reflect.MyClass");
         // 获取方法
         Method method = clazz.getMethod("myMethod", String.class);
         // 创建对象
         Object obj = clazz.newInstance();
         // 调用方法
         method.invoke(obj, "Hello, World!");
     } catch (Exception e) {
         e.printStackTrace();
     }
    
    }
    }

class MyClass {

public void myMethod(String message) {
    System.out.println(message);
}

}输出如下:
Hello, World!

Process finished with exit code 05、反射有什么优缺点
反射的优点:

  1. 动态性:反射可以在运行时动态地获取和操作类的信息,而不需要在编译时确定。
  2. 灵活性:反射可以在运行时根据需要创建对象、调用方法、修改属性等,具有很高的灵活性。
  3. 通用性:反射可以应用于任何Java类,不需要对每个类都编写特定的代码。
    反射的缺点:
  4. 性能问题:反射调用的性能通常比直接调用要低,因为反射需要动态地解析类和方法,这需要额外的时间和资源。
  5. 安全问题:反射可以访问和修改私有属性和方法,这可能会导致安全问题。
  6. 可维护性问题:反射使代码更加复杂,可读性和可维护性可能会受到影响。
    因此,在使用反射时需要权衡其优缺点,根据实际情况选择合适的方案。在性能要求高、安全性要求高或者可维护性要求高的场景中,应该尽量避免使用反射。
    6、反射的应用场景
    反射的应用场景非常广泛,主要包括以下几个方面:
  7. 动态代理:通过反射可以在运行时动态地生成代理类,实现AOP编程,如Spring框架中的AOP功能。
  8. 注解处理器:反射可以用于读取和处理注解信息,如Java EE中的Servlet和JPA注解。
  9. 序列化和反序列化:反射可以用于将对象序列化为字节流或将字节流反序列化为对象,如Java中的ObjectInputStream和ObjectOutputStream类。
  10. 单元测试框架:反射可以用于单元测试框架中的测试用例自动生成,如JUnit框架中的@Test注解。
  11. ORM框架:反射可以用于ORM框架中的实体类和数据库表的映射,如Hibernate框架中的实体类映射。
  12. 动态配置:反射可以用于动态读取和修改配置文件,如Java中的Properties类。
    总之,反射是Java语言中非常重要和常用的特性,可以大大提高程序的灵活性和可扩展性。
    7、反射的几个重要的 API
    Java中的反射机制可以在运行时动态地获取一个类的信息,包括类的属性、方法、构造函数等,并且可以在运行时调用这些属性、方法、构造函数等。反射机制的核心类是java.lang.reflect包下的一些类,下面介绍几个重要的API并用代码说明。
  13. Class类:表示一个类的类型,可以获取类的各种信息。
    Class personClass = Person.class; // 获取Person类的Class对象
    System.out.println(personClass.getName()); // 输出类的全限定名
    System.out.println(personClass.getSimpleName()); // 输出类的简单名称
    Field[] fields = personClass.getDeclaredFields(); // 获取类的所有属性
    for (Field field : fields) {
    System.out.println(field.getName()); // 输出属性名
    }
    Method[] methods = personClass.getDeclaredMethods(); // 获取类的所有方法
    for (Method method : methods) {
    System.out.println(method.getName()); // 输出方法名
    }2. Constructor类:表示一个类的构造函数,可以创建类的实例。
    Constructor constructor = personClass.getDeclaredConstructor(String.class, int.class); // 获取Person类的有参构造函数
    Person person = constructor.newInstance("张三", 20); // 创建Person类的实例
    System.out.println(person.getName()); // 输出"张三"3. Field类:表示一个类的属性,可以获取和修改属性的值。
    Field nameField = personClass.getDeclaredField("name"); // 获取Person类的name属性
    nameField.setAccessible(true); // 设置属性可访问
    nameField.set(person, "李四"); // 修改属性值
    System.out.println(person.getName()); // 输出"李四"4. Method类:表示一个类的方法,可以调用方法并获取返回值。
    Method setNameMethod = personClass.getDeclaredMethod("setName", String.class); // 获取Person类的setName方法
    setNameMethod.invoke(person, "王五"); // 调用方法
    System.out.println(person.getName()); // 输出"王五"8、什么是“反射爆破”
    “反射爆破”是指利用反射机制来破解密码或者进行恶意攻击的一种技术手段。通常情况下,我们使用反射机制是为了更加灵活地操作类的属性、方法等,但是黑客可以通过反射机制来获取类的私有属性、方法等,从而实现对系统的攻击。比如,黑客可以通过反射机制获取某个类的私有属性,然后通过修改属性值的方式来实现对系统的攻击。因此,在编写程序时,我们应该注意对类的属性、方法等进行适当的封装,避免被反射攻击。同时,我们也应该注意程序的安全性,避免被黑客利用反射机制进行攻击。
    class.setAccessible(true)是Java设置后有可能造成“反射爆破”,它可以用于设置类的访问权限。在Java中,类的访问权限分为public、protected、default和private四种。其中,public表示任何类都可以访问,protected表示只有当前类和其子类可以访问,default表示只有同一个包中的类可以访问,private表示只有当前类可以访问。
    当我们使用class.setAccessible(true)时,就可以设置当前类的访问权限,使得即使该类的访问权限为private,也可以通过反射机制来访问该类的私有属性、方法等。这种机制虽然可以提高程序的灵活性和可扩展性,但同时也增加了程序的安全风险,因此在使用时需要谨慎,避免被黑客利用反射机制进行攻击。
目录
相关文章
|
1月前
|
安全 Java 数据库连接
如何理解反射
反射之所以被称为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。
55 5
|
安全 Java 测试技术
带你深入学习“反射”技术
带你深入学习“反射”技术
113 1
带你深入学习“反射”技术
|
前端开发 编译器 容器
|
网络协议 测试技术 Go
反射的引出和应用场景|学习笔记
快速学习反射的引出和应用场景
|
算法 安全 C#
C#反射与特性(一):反射基础
C#反射与特性(一):反射基础
272 0
C#反射与特性(一):反射基础
|
程序员 编译器 API
C#反射与特性(九): 全网最全-解析反射
C#反射与特性(九): 全网最全-解析反射
356 0
C#反射与特性(九): 全网最全-解析反射
|
Java C# C++
实战中反射的应用
实战中反射的应用
128 0
实战中反射的应用
C#反射与特性(二):探究反射
C#反射与特性(二):探究反射
212 0
|
Java 开发者
反射与 NEW | 学习笔记
快速学习反射与 NEW。
131 0