Java高级-反射

news2025/2/26 6:18:02

反射

  • 1.介绍
  • 2.获取Class对象的三种方法
  • 3.获取类的构造器
  • 4.获取类的成员变量
  • 5.获取类的成员方法
  • 6.反射的作用和应用场景

1.介绍

反射

  • 加载类,并允许以编程的方式解剖类的各种成分(成员变量、方法、构造器等)

反射步骤

  • 1.加载类,获取类的字节码:Class对象
  • 2.获取类的构造器:Constructor对象
  • 3.获取类的成员变量:Field对象
  • 4.获取类的成员方法:Method对象

2.获取Class对象的三种方法

获取Class对象的三种方法

  • Class c1 = 类名.class
  • 调用Class的方法: public static Class forName(String package);
  • Object提供的方法:public Class getClass(); Class c3 = 对象.getClass;
public class Test1Class {
    public static void main(String[] args) throws ClassNotFoundException {
        // 第一种
        Class c1 = Student.class;
        System.out.println(c1.getName()); // 全类名 advanced.reflex.Student
        System.out.println(c1.getSimpleName()); // 类名 Student

        // 第二种
        Class<?> c2 = Class.forName("advanced.reflex.Student");

        // 第三种
        Student s = new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c3 == c2);
    }
}

3.获取类的构造器

  • getDeclaredConstructors (推荐)
  • getDeclaredConstructor (推荐)
  • 不建议在反射中加泛型,为了通用性
    在这里插入图片描述
/**
 * 目标:获取类的构造器,并对其进行操作
 */
public class Test2Constructor {

    @Test
    public void testGetConstructors() {
        // 1.必须先得到类的class对象
        Class<Cat> catClass = Cat.class;
        // 2.获取类的全部构造器
		// Constructor[] constructors = catClass.getConstructors();
        Constructor[] constructors = catClass.getDeclaredConstructors();
        // 3.遍历数组的中构造器对象
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
        }
    }

    @Test
    public void testGetConstructor() throws NoSuchMethodException {
        // 1.必须先得到类的class对象
        Class<Cat> catClass = Cat.class;
        // 2.获取类的某个构造器
		// Constructor<Cat> constructor = catClass.getConstructor();
        Constructor<Cat> constructor = catClass.getDeclaredConstructor();
        System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());

        // 3.获取有参的构造器
        Constructor<Cat> constructor2 = catClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor2.getName() + "--->" + constructor2.getParameterCount());
    }
}

获取类构造器的作用
获取类构造器的作用:依然是初始化对象返回
在这里插入图片描述

@Test
public voidtestGetConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    // 1.必须先得到类的class对象
    Class<Cat> catClass = Cat.class;
    // 2.获取类的某个构造器
    Constructor constructor = catClass.getDeclaredConstructor();
    constructor.setAccessible(true);
    Cat cat = (Cat) constructor.newInstance();
    System.out.println(cat);

    // 3.获取有参的构造器
    Constructor constructor2 = catClass.getDeclaredConstructor(String.class, int.class);
    constructor2.setAccessible(true);
    Cat cat2 = (Cat) constructor2.newInstance("叮当猫", 12);
    System.out.println(cat2);
}

4.获取类的成员变量

在这里插入图片描述

public class Cat {
    private static int a;
    public static final String COUNTRY = "中国";
    private String name;
    private int age;
}
@Test
public void getGetFields() throws NoSuchFieldException {
    // 1.获取Class对象
    Class catClass = Cat.class;
    // 2.获取类的全部成员变量
    Field[] fields = catClass.getDeclaredFields();
    // 3.遍历成员变量数组
    for (Field field : fields) {
        System.out.println(field.getName() + "---" + field.getType());
    }

    // 4.定位某个成员变量
    Field fName = catClass.getDeclaredField("name");
    System.out.println(fName.getName() + "-->" + fName.getType());

    Field fAge = catClass.getDeclaredField("age");
    System.out.println(fAge.getName() + "-->" + fAge.getType());
}

获取成员变量的作用
获取成员变量的作用:赋值和取值
在这里插入图片描述

@Test
public void getGetFields() throws Exception {
    // 1.获取Class对象
    Class catClass = Cat.class;
    // 2.定位某个成员变量
    Field fName = catClass.getDeclaredField("name");
    System.out.println(fName.getName() + "-->" + fName.getType());
    
    // 赋值
    Cat cat = new Cat();
    fName.setAccessible(true);
    fName.set(cat, "加菲猫");
    System.out.println(cat);

    // 取值
    String name = (String) fName.get(cat);
    System.out.println("name = " + name);
}

5.获取类的成员方法

在这里插入图片描述

private void run() {
   System.out.println("猫跑的很快");
}

private void eat() {
    System.out.println("猫爱吃猫粮");
}
private String eat(String name) {
    return "猫爱吃" + name;
}
@Test
public void testGetMethods() throws Exception {
    // 1.获得Class对象
    Class catClass = Cat.class;
    // 2.获取类的全部成员方法
    Method[] methods = catClass.getDeclaredMethods();
    // 3.遍历
    for (Method method : methods) {
        System.out.println(method.getName() + "---" +
                method.getParameterCount() + "---" +
                method.getReturnType());
    }

    // 4.获取某个方法对象
    Method run = catClass.getDeclaredMethod("run");
    System.out.println(run.getName() + "---" +
            run.getParameterCount() + "---" +
            run.getReturnType());

    Method eat = catClass.getDeclaredMethod("eat", String.class);
    System.out.println(eat.getName() + "---" +
            eat.getParameterCount() + "---" +
            eat.getReturnType());
}

获取成员方法的作用
获取成员方法的作用:执行此方法在这里插入图片描述

@Test
public void testGetMethods() throws Exception {
    // 1.获得Class对象
    Class catClass = Cat.class;
    // 2.获取某个方法对象
    Method run = catClass.getDeclaredMethod("run");
    Method eat = catClass.getDeclaredMethod("eat", String.class);

    // 执行方法
    Cat cat = new Cat();
    run.setAccessible(true);
    Object rs = run.invoke(cat);// 调用无参数的run方法,用cat对象触发调用
    System.out.println("rs = " + rs);
    
    eat.setAccessible(true);
    rs = eat.invoke(cat, "火腿肠");
    System.out.println("rs = " + rs);
}

6.反射的作用和应用场景

反射的作用

  • 基本作用:可以得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 最重要的用途:适合做Java的框架

案例:使用反射做一个简易版的框架
需求:

  • 对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去

实现步骤

  • 1.定义一个方法,可以接收任意对象
  • 2.每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
  • 3.遍历成员变量,然后提取成员变量在该对象中的具体值
  • 4.把成员变量名、值,写出到文件中去即可
public class Student {
    private String name;
    private char sex;
    private int age;
    private double height;
    private String hobby;
}

public class Teacher {
    private String name;
    private double salary;
}
/**
 * 使用反射技术,设计一个保存对象的简易版框架
 */
public class Test5Frame {
    @Test
    public void save() throws Exception{
        Student s1 = new Student("吴彦祖", '男', 45, 185.3, "乒乓球");
        Teacher t1 = new Teacher("黄子韬", 999.9);

        // 需求:任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去
        ObjectFrame.saveObject(s1);
        ObjectFrame.saveObject(t1);
    }
}
/**
 * 保存任意对象的字段和数据到文件中去
 */
public class ObjectFrame {

    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("F:\\Code\\JetBrains-Work\\Java\\2022study\\src\\advanced\\reflex\\data.txt", true));
        // obj是任意对象,到底有多少个字段要保存
        Class c = obj.getClass();
        String cName = c.getSimpleName();
        ps.println("-------------------" + cName + "-------------------");
        // 2.从该类中提取全部成员变量
        Field[] fields = c.getDeclaredFields();
        // 3.变量每个成员变量
        for (Field field : fields) {
            // 4.拿到成员变量的名字
            String name = field.getName();
            // 5.拿到这个成员变量在该对象的值
            field.setAccessible(true);
            String value = field.get(obj).toString();
            ps.println(name + "=" + value);
        }
        ps.close();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1027448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hiding Images within Images[精读]

Hiding Images within Images 第一次阅读时间&#xff1a;2023/9/15-2023/9/20 这里写目录标题 Hiding Images within Images1 背景介绍2 论文摘要3 相关工作3.1 隐藏信息的目的3.2 隐藏信息面临的挑战3.3 常见的隐藏技术3.4 和隐写术(steganography)的区别 4 提出方法4.1 学…

Nginx多出口IP解决代理端口数量限制,CentOS安装Nginx并开启https2.0

Nginx多出口IP解决代理端口数量限制,CentOS安装Nginx并开启https2.0。 配置文件如下: http {...upstream test {server www.test.com;}server {listen 80 default_server;server_name _;location / {proxy_pass http://test;proxy_bind $split_ip

BD就业复习第一天

hive 1.分区分桶 在Hive中&#xff0c;分区&#xff08;Partition&#xff09;和分桶&#xff08;Bucketing&#xff09;都是用于数据管理和查询性能优化的技术。它们有不同的用途和特点。 分区&#xff08;Partition&#xff09;&#xff1a; 定义&#xff1a;分区是将数据…

【UE 粒子练习】03——创建一个GPU粒子

目的 为了实现创建非常多的粒子的需求&#xff0c;我们就需要使用到GPU 效果 步骤 1. 复制一份上篇博文中创建的粒子&#xff0c;这里重命名为“P_Sparks_GPU” 打开“P_Sparks_GPU”&#xff0c;将生成的粒子数量改为2000&#xff0c;可以看到发射器最多只能生成1000个粒子…

【Java 基础篇】Java 生产者-消费者模式详解

Java 生产者-消费者模式是多线程编程中常见的一种模式&#xff0c;它用于解决生产者和消费者之间的协作问题。生产者负责生成数据&#xff0c;消费者负责处理数据&#xff0c;通过合理的协作&#xff0c;可以实现高效的数据处理。本文将详细介绍 Java 生产者-消费者模式&#x…

使用 WSLg 的 vGPU 硬件加速新特性创建重度混合生产环境

使用 WSLg 的 vGPU 硬件加速新特性创建重度混合生产环境 本文首发于&#xff1a;白泽阁-使用 WSLg 的 vGPU 硬件加速新特性创建重度混合生产环境 一、不同版本的WSL Windows Subsystem for Linux&#xff08;简称WSL&#xff09;是一个在 Windows 10\11 上能够运行原生Linux…

c语言练习64:calloc和realloc

calloc和realloc C语⾔还提供了⼀个函数叫 calloc &#xff0c; calloc 函数也⽤来动态内存分配 和realloc是有区别的 练习使用calloc和realloc realloc在c语言练习63中有所应用&#xff0c;realloc是为了扩大内存空间 下面为calloc和recalloc的例子代码: #include<stdio…

肖sir___环境的讲解__001

环境的讲解 一、搭建环境 此测试环境主要用于功能测试、寻找bug、编写后台测试点、熟悉环境的架构&#xff0c;搭建流程 二、搭建多有米前后台所需要的工具包 1、虚拟机&#xff08;centos6.5&#xff09; 2、数据库 3、代码包 4、服务器 5、数据库脚本 6、jdk 三、搭建测试…

【简洁】【皮肤美化】博客园页面美化 主文章加宽

效果&#xff1a; 选择&#xff1a;Bluesky皮肤 再加入的css: #home {background-color: #e6e6e6; } #top_nav{ background-color: #e6e6e6; } #navigator, #under_post_card1, #ad_t2 , #nav_right, #nav_left, #cnblogs_c1, #under_post_card2, #HistoryToday, #green_chann…

持续集成Jenkins安装部署

Jenkins是一个在DevOps领域中、支持CI/CD&#xff08;持续集成/持续交付&#xff09;过程域的开源项目&#xff0c;其提供可扩展插件的支持&#xff0c;以自动化的机制对项目工程执行打包、编译、构建、测试以及最终发布到目的地服务器并成功部署运行&#xff0c;本文主要描述J…

HR对职业发展进行思考

如果你还没有职业发展方面的思考&#xff0c;请不要怪自己&#xff0c;这很正常。没有谁是一开始就会如此清晰理性地对职业发展进行思考。 笔者对职业发展有关话题进行系统性的思考&#xff0c;得益于两本书&#xff1a; 第一本是哈佛大学泰勒本-沙哈尔教授的《幸福的方法》&…

Git(10)——Git多人协同开发之邀请成员

一、简介 本篇文章接着第九章介绍Git多人协同开发如何邀请成员 二、创建dev分支 前面已经提到master只用于上线正式代码&#xff0c;因此需要创建一个专门用于开发的dev分支 ①使用如下命令创建dev分支并切换到dev分支 git checkout -b dev ②将dev分支上传至远端仓库&…

Redis分布式锁及其常见问题解决方案

Redis 是一种内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息代理。由于其高性能和灵活的数据结构&#xff0c;Redis 被广泛应用在各种场景中&#xff0c;包括实现分布式锁。 分布式锁是一种在分布式系统中实现互斥访问的技术。在许多实际应用场景中&#x…

MyBatis基础之执行SQL

文章目录 执行 SQL 语句1. 增删改操作insert 元素insert 过程中的主键回填delete 元素 和 update 元素 2. getMapper 方法3. 查操作select 元素select 与 聚合函数 4. 传递多个参数使用 Map 传递多参数使用 JavaBean 传递多参使用注解方式传递多参数 执行 SQL 语句 Mapper 是 …

1999-2018年地级市一般公共预算收入、支出(教育事业费、科技支出)

1999-2018年地级市一般公共预算收入、支出&#xff08;教育事业费、科技支出&#xff09; 1、时间&#xff1a;1999-2018年 2、来源&#xff1a;城市年鉴 3、指标&#xff1a;行政区划代码、城市、年份、地方一般公共预算收入_市辖区_万元、地方一般公共预算支出_市辖区_万元…

云效+主机部署解决方案(需求->开发->测试->发布->运维->运营)

文章目录 引言I Maven相关1.1 阿里云私有仓库-迁移本地仓库至私有仓库II 代码管理2.1 初始化仓库脚本2.2 分支模式:分支开发、主干发布“的模式III 集成3.1 开启分支模式IV 创建阿里云子账号(RAM)V 安全组端口访问规则配置IV 阿里云的日志服务 SLSsee also引言 Flow语言专项…

性能测试 —— Tomcat监控与调优:status页监控

Tomcat服务器是一个免费的开放源代码的Web 应用服务器&#xff0c;Tomcat是Apache 软件基金会(Apache Software Foundation)Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun 和其他一些公司及个人共同开发而成。 Tomcat是一个轻量级应用服务器&#xff0c;在中小型系统…

1787_函数指针的使用

全部学习汇总&#xff1a;GitHub - GreyZhang/c_basic: little bits of c. 前阵子似乎写了不少错代码&#xff0c;因为对函数指针的理解还不够。今天晚上似乎总算是梳理出了一点眉目&#xff0c;在先前自己写过的代码工程中做一下测试。 先前实现过一个归并排序算法&#xff0c…

Java并发编程第8讲——ThreadLocal详解

ThreadLocal无论是在项目开发还是面试中都会经常碰到&#xff0c;它的重要性可见一斑&#xff0c;本篇文章就从ThreadLocal的使用、实现原理、核心方法的源码、内存泄漏问题等展开介绍一下。 一、什么是ThreadLocal ThreadLocal是java.lang下面的一个类&#xff0c;在JDK 1.2版…

植隆业务中台与金蝶云星空对接集成服务工单查询接口连通应收单新增(6202-开票申请(代理商-销售类))

植隆业务中台与金蝶云星空对接集成服务工单查询接口连通应收单新增(6202-开票申请&#xff08;代理商-销售类&#xff09;) 数据源系统:植隆业务中台 承载了企业核心关键业务&#xff0c;是企业的核心业务能力&#xff0c;也是企业数字化转型的重点。业务中台的建设目标是&…