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

什么是JAVA反射??? 常用的API有哪些???怎么获取Class对象.....

目录

引言:

一、获取Class对象的方法

二、使用反射获取构造方法

三、使用反射获成员变量的方法

四、使用反射获成员方法

五.反射的优缺点有哪些?

优点包括:

缺点包括:

总结:


引言:

什么是反射:反射其实我们很早就知晓了,比如我们经常访问一个对象的方法,idea给的提示就是通过反射来获取的(dogo!!!)
反射技术作为编程语言中的一项强大工具,允许我们在运行时对类的字段方法构造函数进行编程访问。这一特性使得反射在框架设计、插件系统、单元测试等场景中有着广泛的应用。本文将详细介绍如何通过反射技术获取Class对象,进而访问类的构造方法、属性和方法。

简而言之反射就是霸道的,在反射面前,就是透明的!!!我可以随意获取到你的任何属性信息,然后去操作本且去修改它!!!

使用方法:

主要包括2个步骤:获取 解剖

首先获取class 对象,然后通过class 对象获取到我们想要的属性,比如成员变量,构造方法,成员方法。然后通过这些就可以再次细获取他们信息,比如(类型,名字,修饰符...) ,甚至你还可以去修改他们的值!!!(包括私有的属性)所有说反射就是破坏封装性的!!!

详细如下: 


一、获取Class对象的方法

在反射技术中,获取Class对象是进行后续操作的基础。以下是三种获取Class对象的方法:

自定义了一个学生类:私已成员变量和私有set方法共有get方法,后续演示:

package com.hz.example;

public class Student {
    private String name;

    private int age;

    public Student() {
    }
    public Student(String name) {}
    private Student( int age) {
        this.age = age;
    }
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    private void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    private void setName(String name) {
        this.name = name;

    }

    private void eat(String something){
        System.out.println("Student is eating "+something);
    }
    private String eat(String something1,int munch){
       return "Student is eating "+something1+" and he has eaten"+munch+"no of times";
    }
    public void show(){
        System.out.println("Student is eating");
    }
}
  1. 通过类名获取:  使用Class.forName(String className)方法,其中className为类的全类名(包名 +类名)(快捷键 :鼠标点击你要获取的类 然后:ctrl +alt + shift + c)  例如,Class<?> clazz = Class.forName("com.hz.example.Student"); 此方法会源代码阶段去调用java 文件 -> class文件

  2. 通过类字面量获取:使用类名.class的方式。这是最直接、最常用的获取Class对象的方法。例如,Class<?> clazz = Student.class;(加载阶段使用)

  3. 通过对象获取:使用对象.getClass()方法。如果已有一个类的实例对象,可以通过该方法获取其Class对象。例如,Student student = new Student();; Class<?> clazz = Student.getClass(); (运行阶段使用)

使用场景总结:

  • Class.forName:适用于需要根据字符串形式的类名动态加载类的情况,常用于框架设计、插件机制等。
  • 对象.getClass:适用于已有一个类的实例对象,需要获取该对象的 Class 对象以进行反射操作的情况。
  • 类名.class:适用于编译时就已知要操作的类,是最简单、最常用的获取 Class 对象的方法。

二、使用反射获取构造方法

获取了Class对象后,我们就可以通过反射来获取类的构造方法。构造方法分为私有和公有两种,通过反射我们可以访问这两种构造方法。

小知识: 在java中,万物接可对象,java中也定义了相应的类来描述构造方法,成员方法,成员变量:

  1. 构造方法:  Constructor
  2. 成员方法;     Method
  3. 成员变量:   Field

 通过这些就可以很快获取到相应对象,进而去操作他们!!!

  1. 获取所有构造方法

    1. 使用Class.getConstructors()方法获取所有公有的构造方法;构造方法就是通过Constructor获取,然后加s 就是获取所有公共的构造方法,返回的就是数组,

    2. 使用Class.getDeclaredConstructors()方法获取所有(包括私有)构造方法。Declared就是权限的意思,那么类似root 你可以获取所有的,包括私有的,然后下面获取成员变量,方法也一样了!!

  2. 获取特定构造方法

    1. 使用Class.getConstructor(Class<?>... parameterTypes)方法根据参数类型获取公有的构造方法,(没加s,就表示获取单个的,本且没有加Declared,就自然获取指定公共的)      

    2. 使用Class.getDeclaredConstructor(Class<?>... parameterTypes)方法根据参数类型获取所有(包括私有)构造方法。

  3. 创建对象:获取了构造方法后,可以

    1. 使用Constructor.newInstance(Object... initargs)方法来创建对象实例

    2. 当然,有时候私已的private还得用 setAccessible(boolen flag) 去更改它的权限为true 才可以去操作:

简单Demo: 


            // 通过类名获取Class对象
            Class<?> aClass = Class.forName("com.hz.example.Student");

            // 获取类的所有公共构造方法
            Constructor<?>[] constructors = aClass.getConstructors();

            // 获取类的所有构造方法,包括私有、受保护和默认访问级别的构造方法
            Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();

            // 获取接受一个String类型参数的公共构造方法
            Constructor<?> constructor = aClass.getConstructor(String.class);

            // 获取接受一个String类型和一个int类型参数的私有构造方法
            Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
            // 设置该构造方法为可访问
            declaredConstructor.setAccessible(true);
            // 使用该构造方法创建Student对象
            Student student = (Student) declaredConstructor.newInstance("张三", 18);

原Demo: 

三、使用反射获成员变量的方法

其实下面也差不多了!! 

Class类中用于获取成员变量的方法


Field[] getsields():        返回所有公共成员变量对象的数组
Field[]getDeclaredFields():        返回所有成员变量对象的数组
Field getField(String name):        返回单个公共成员变量对象
Field getDeclaredField(String name):        返回单个成员变量对象


Field类中用于创建对象的方法
void set(Object obj, Object value):        赋值
Object get(Object obj)         获取值。

参考Demo: 

// 获取Student类的Class对象
Class<?> aClass = Class.forName("com.hz.example.Student");

// 获取Student类的所有公共字段(包括继承自父类的字段)
Field[] fields = aClass.getFields();
for (Field field : fields) {
    // 打印每个公共字段的信息
    System.out.println(field);
}

// 获取Student类声明的所有字段,包括私有字段,但不包括继承的字段
Field[] declaredFields = aClass.getDeclaredFields();

// 通过字段名获取Student类的公共字段对象"name"
Field name = aClass.getField("name");
System.out.println(name);

// 获取字段名
String name1 = name.getName();

// 获取字段类型
Class<?> type = name.getType();
System.out.println(name1 + "  " + type);

// 创建Student类的实例对象
Student student = new Student("hz");

// 设置字段可访问性,以便可以访问私有字段
name.setAccessible(true);

// 通过反射获取student对象"name"属性的值
Student value = (Student) name.get(student);
System.out.println("通过反射获取 创建对象name属性的值value = " + value);

// 通过反射修改student对象"name"属性的值为"mn"
name.set(student, "mn");

// 打印修改后的"name"属性值
System.out.println("修改后的name的值为:" + student.getName());

四、使用反射获成员方法

Class类中用于获取成员方法的方法:


Method[]getMethods():返回所有公共成员方法对象的数组,包括继承的
Methodl] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>.. parameterTypes):返回单个成员方法对象


Method类中用于创建对象的方法;


Object invoke(Object obj, Object... args):运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

getMethodsgetDeclaredMethods 区别,getMethods获取公共以外,还会获取父类的方法:我这里没有,但是有一个祖宗 Object !!!!

getMethod getDeclaredMethod获取 指定方法的时候: 除了指定方法的名字外,还得去指定他们的参数类型,主要是区分方法重载!!!!(其实和什么类似,构造方法因为名字都一样,不用指定,但是也指定了参数的类型,这些都是类似的!!!)

invoke() 运行方法:

// 获取Student类的Class对象
Class<?> aClass = Class.forName("com.hz.example.Student");

// 通过反射获取Student类中名为"eat"的方法,该方法接收一个String类型的参数
Method eat = aClass.getDeclaredMethod("eat", String.class);

// 设置该方法为可访问,即使它是私有的也可以被访问
eat.setAccessible(true);

// 创建Student类的实例
Student student = new Student();

// 调用Student对象的eat方法,并传入"苹果"作为参数
// 注意:由于eat方法没有返回值,因此这里不需要处理返回值
// 原eat 方法没有返回值 就不用管
eat.invoke(student,"苹果");

// 通过反射获取Student类中名为"eat"的另一个方法,该方法接收一个String类型和一个int类型的参数
Method eat1 = aClass.getDeclaredMethod("eat", String.class, int.class);

// 同样设置该方法为可访问
eat1.setAccessible(true);

// 调用Student对象的eat方法,并传入"蔡徐坤"和999作为参数
// 由于该方法有返回值,且我们期望返回值为String类型,因此进行类型转换
String invoke = (String) eat1.invoke(student, "蔡徐坤", 999);

// 打印返回值
System.out.println(invoke);

五. 反射的优缺点有哪些?


优点包括:

  1. 动态性:反射允许在运行时动态地获取和操作类的信息,而不需要在编译时知道类的具体细节。
  2. 灵活性:反射可以通过类名字符串来创建对象实例,可以在运行时动态地调用方法和字段,以及访问和修改私有成员。
  3. 扩展性:反射可以用于实现一些高级功能,如动态代理、注解处理和依赖注入等。


缺点包括:

  1. 性能损耗:由于反射需要在运行时获取和操作类的信息,所以相比直接调用,反射操作通常会导致性能下降。
  2. 安全问题:反射可以访问和修改私有成员,这可能破坏了封装性和安全性,因此,在使用反射时需要谨慎处理权限和访问控制。
  3. 编码复杂性:反射的使用和理解相对复杂,容易引入错误和难以调试。同时,反射操作也不受编译器的类型检查,可能导致运行时异常。

六. 总结:


反射技术为我们在运行时动态地访问和修改类的字段、方法和构造函数提供了强大的能力。在实际应用中,反射技术有着广泛的应用场景,如框架设计、插件系统、单元测试等。然而,反射技术也带来了一定的性能开销和安全性问题,因此在使用时需要权衡其利弊。


http://www.kler.cn/a/420298.html

相关文章:

  • 互联网 Java 面试八股文汇总(2025 最新整理)
  • 工作:三菱PLC防止程序存储器爆满方法
  • 【网络】协议与网络传输
  • THENA大涨将对整个DeFi市场产生怎样的影响?
  • WEB开发: 丢掉包袱,拥抱ASP.NET CORE!
  • 详细了解索引规约
  • 循环神经网络设计同样可以使用预训练词“嵌入”
  • 20241129解决在Ubuntu20.04下编译中科创达的CM6125的Android10出现找不到库文件libtinfo.so.5的问题
  • 【Java基础】笔记
  • MySQL 索引创建 大数据查询 性能测试 SQL优化 慢查询
  • 游戏引擎学习第30天
  • C#面向对象之访问限制,类基础,继承
  • QT:将QTableWidget内容写入txt文件中
  • Go-Web之TCP网络连接
  • HTTPS 的安全秘密:对称加密与非对称加密的完美结合
  • Python学习38天
  • 【赵渝强老师】PostgreSQL的物理存储结构
  • 【jvm】C1编译器和C2编译器的区别
  • 解决maya渲染慢、渲染卡顿等问题
  • Qt/C++实现帧同步播放器/硬解码GPU绘制/超低资源占用/支持8K16K/支持win/linux/mac/嵌入式/国产OS等
  • 详解Qt pdf 之QPdfSelection 选择文本类
  • debian 11 虚拟机环境搭建过坑记录
  • 机器学习7-AdaBoost算法
  • Springboot聚合工程实现不同module使用不同的数据库配置操作数据库,实现自由切库
  • CTF-PWN: 全保护下格式化字符串利用 [第一届“吾杯”网络安全技能大赛 如果能重来] 赛后学习(不会)
  • 《Serverless 架构:引领未来软件开发的新趋势》