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

目录

引言:

一、获取Class对象的方法

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

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

四、使用反射获成员方法

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

优点包括:

缺点包括:

总结:


引言:

什么是反射:反射其实我们很早就知晓了,比如我们经常访问一个对象的方法,idea给的提示就是通过反射来获取的(dogo!!!)

反射技术作为编程语言中的一项强大工具,允许我们在运行时对类的字段方法构造函数 进行编程访问。这一特性使得反射在框架设计、插件系统、单元测试等场景中有着广泛的应用。本文将详细介绍如何通过反射技术获取Class对象,进而访问类的构造方法、属性和方法。

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

使用方法:

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

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

详细如下:


一、获取Class对象的方法

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

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

java 复制代码
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:

java 复制代码
            // 通过类名获取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:

java 复制代码
// 获取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 !!!!

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

invoke() 运行方法:

java 复制代码
// 获取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. 编码复杂性:反射的使用和理解相对复杂,容易引入错误和难以调试。同时,反射操作也不受编译器的类型检查,可能导致运行时异常。

六. 总结:

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

相关推荐
人才程序员13 分钟前
详解QtPDF之 QPdfLink
开发语言·c++·qt·pdf·软件工程·界面·c语音
梦.清..18 分钟前
C语言——指针基础
c语言·开发语言
paopaokaka_luck24 分钟前
[384]基于springboot的药品管理系统
java·spring boot·后端
DreamByter30 分钟前
Day4:生信新手笔记 — R语言简单命令与Rstudio配置
开发语言·笔记·r语言
老马啸西风42 分钟前
Neo4j APOC-01-图数据库 apoc 插件介绍
java
名字不要太长 像我这样就好1 小时前
【iOS】《Effective Objective-C 2.0》阅读笔记(一)
开发语言·笔记·学习·macos·ios·objective-c
次次皮1 小时前
【方案三】JAVA中使用ocr(Umi-OCR)
java·ocr
九转成圣1 小时前
详解日志格式配置:XML 与 Spring Boot 配置文件格式
xml·spring boot·后端
疯一样的码农1 小时前
如何使用Apache HttpClient发送带有HTML表单数据的POST请求
java·apache·httpclient