Java中的反射使用

news2024/11/25 4:43:03

1、获取Class对象的三种方式

1、对象调用Object类的getClass()方法(对象.getClass())

2、调用类的class属性(类名.class)

3、调用Class类的静态方法(Class.forName(“包名.类名”))常用

Student类

package com.example.reflection;

public class Student {
}

测试类

public class Demo {
    public static void main(String[] args) {
        //对象调用父类Object的getClass()方法
        Student student = new Student();
        Class<? extends Student> clazz = student.getClass();
        System.out.println(clazz);

        //调用类的class属性
        Class<Student> stu = Student.class;
        System.out.println(stu);

        //调用Class类的静态方法forName()向方法中传一个字符串(包名.类名)
        try {
            Class<?> c = Class.forName("com.example.reflection.Student");
            System.out.println(c);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
获取Class对象的三种方式

2、获取构造方法

1、getConstructors() 获取被public修饰构造方法

2、getDeclaredConstructors() 获取所有构造方法(包括:private、protected、默认、public)

3、getConstructor(参数类型…) 获取单个被public修饰构造方法 (参数类型为可变参数,有几个参数就写几个,值为null时,表示获取无参构造)

4、getDeclaredConstructor(参数类型…) 根据参数类型获取单个构造方法(包括:private、protected、默认、public),参数类型同getConstructor一样

5、setAccessible(true) Constructor对象调用该方法 暴力访问该方法,忽略掉所有访问修饰符

Student类

package com.example.reflection;

public class Student {

    /**
     * 默认构造方法
     *
     * @param str 形参
     */
    Student(String str) {
        System.out.println("默认构造方法执行了...");
    }

    /**
     * 无参构造方法
     */
    public Student() {
        System.out.println("无参构造方法执行了...");
    }

    /**
     * 一个参数的构造方法
     *
     * @param age 年龄
     */
    public Student(int age) {
        System.out.println("年龄:" + age);
    }

    /**
     * 多参构造方法
     *
     * @param name     姓名
     * @param age      年龄
     * @param password 密码
     */
    public Student(String name, int age, String password) {
        System.out.println("姓名:" + name + "年龄:" + age + "密码:" + password);
    }

    protected Student(boolean n) {
        System.out.println("受保护的构造方法执行了..." + n);
    }

    /**
     * 私有构造方法
     *
     * @param sex 性别
     */
    private Student(char sex) {
        System.out.println("私有构造方法执行了..." + sex);
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        try {
            //加载Class对象
            Class<?> clazz = Class.forName("com.example.reflection.Student");
            //获取所有公有构造方法
            Constructor<?>[] constructors = clazz.getConstructors();
            System.out.println("公有构造方法:");
            System.out.println(Arrays.toString(constructors));
            System.out.println("=======================");

            constructors = clazz.getDeclaredConstructors();
            System.out.println("所有构造方法(包括私有、受保护、默认和公有):");
            System.out.println(Arrays.toString(constructors));

            System.out.println("=======================");
            System.out.println("公有无参构造方法:");
            Constructor<?> con = clazz.getConstructor(null);
            System.out.println(con);

            System.out.println("=======================");
            con = clazz.getConstructor(int.class);
            System.out.println("公有有参构造方法:");
            System.out.println(con);

            System.out.println("=======================");
            con = clazz.getDeclaredConstructor(char.class);
            System.out.println("私有有参构造方法:");
            System.out.println(con);

            System.out.println("=======================");
            System.out.println("暴力访问(忽略掉访问修饰符):");
            Constructor<?> c = clazz.getDeclaredConstructor(char.class);
            c.setAccessible(true);
            c.newInstance('男');
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
获取构造方法

3、获取成员变量并调用

1、getFields() 获取所有被public修饰字段

2、getDeclaredFields() 获取所有字段(包括:private、protected、默认、public)

3、getField(字段名) 根据字段名获取被public修饰字段

4、getDeclaredField(字段名) 根据字段名获取字段(包括:private、protected、默认、public所修饰的字段)

Student

package com.example.reflection;

public class Student {
    public int height;
    double weight;
    private String name;
    private int age;
    private char sex;
    private String password;
    
    /**
     * 无参构造方法
     */
    public Student() {
        System.out.println("无参构造方法执行了...");
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.example.reflection.Student");
            Field[] fields = clazz.getFields();
            System.out.println("获取所有公有的字段:");
            System.out.println(Arrays.toString(fields));

            System.out.println("=======================");
            fields = clazz.getDeclaredFields();
            System.out.println("获取所有字段(包括私有、受保护、默认和公有):");
            System.out.println(Arrays.toString(fields));

            System.out.println("=======================");
            System.out.println("获取公有的字段并赋值:");
            Field height = clazz.getField("height");
            System.out.println("身高:" + height);
            Object obj = clazz.getConstructor().newInstance();
            height.set(obj, 180);
            Student stu = (Student) obj;
            System.out.println("学生身高:" + stu.height + "cm");

            System.out.println("=======================");
            System.out.println("获取默认字段并赋值:");
            Field weight = clazz.getDeclaredField("weight");
            System.out.println("体重:" + weight);
            weight.set(obj, 82.5);
            System.out.println("学生体重:" + stu.weight + "kg");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
获取成员变量

4、获取成员方法并调用

1、getMethods() 获取所有被public所修饰的成员方法

2、getDeclared() 获取所有成员方法(包括:private、protected、默认、public)

3、getMethod(方法名称,方法参数…) 根据方法名称、参数获取被public修饰的方法

4、getDeclaredMethod(方法名称,方法参数…) 根据方法名称、参数获取默认、被protected修饰的方法

5、Method中的invoke(对象,参数值…)可以执行方法,若要执行被private修饰的方法,需要设置Method对象.setAccessible(true)解除私有限定

Student

package com.example.reflection;

public class Student {
    /**
     * 无参构造方法
     */
    public Student() {
        System.out.println("无参构造方法执行了...");
    }

    public void test1(String str) {
        System.out.println("调用了公有的、String参数的方法" + str + "...");
    }

    protected void test2() {
        System.out.println("调用了受保护的、无参的方法test2...");
    }
    
    void test3() {
        System.out.println("调用了默认的、无参的方法test3...");
    }

    private static String test4(int age) {
        System.out.println("调用了私有的、有参、有返回值的方法test4..." + age);
        return "test4的返回值";
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("com.example.reflection.Student");
            Method[] methods = clazz.getMethods();
            System.out.println("获取所有公有的成员方法:");
            System.out.println(Arrays.toString(methods));

            System.out.println("=======================");
            methods = clazz.getDeclaredMethods();
            System.out.println("获取所有成员方法(包括私有、受保护、默认和公有):");
            System.out.println(Arrays.toString(methods));

            System.out.println("=======================");
            Method test1 = clazz.getMethod("test1", String.class);
            System.out.println(test1);
            Object obj = clazz.getConstructor().newInstance();
            test1.invoke(obj, "test1");

            System.out.println("=======================");
            Method test3 = clazz.getDeclaredMethod("test3");
            System.out.println(test3);
            test3.invoke(obj);

            System.out.println("=======================");
            Method test4 = clazz.getDeclaredMethod("test4", int.class);
            System.out.println(test4);
            test4.setAccessible(true); //解除私有限定
            Object result = test4.invoke(obj, 15);
            System.out.println("返回值:" + result);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

获取成员方法

5、获取main方法并执行

Student

package com.example.reflection;

public class Student {
    public static void main(String[] args) {
        System.out.println("Student中的main方法执行了...");
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
        try {
            //1、获取Student的字节码文件
            Class<?> clazz = Class.forName("com.example.reflection.Student");
            //2、获取main方法
            Method main = clazz.getMethod("main", String[].class);
            //3、调用main方法
            //      第一个参数:对象类型,因为方法时静态的,所有为null可以
            //      第二个参数:String数组,这里要注意在JDK1.4之后是数组,JDK1.5之后为可变参数
            //      这里拆的时候将new String[]{"a","b","c"}拆成3个对象所有需要强制转换
            main.invoke(null, (Object) new String[]{"a", "b", "c"});
//            main.invoke(null,new Object[]{new String[]{"a","b","c"}}); //这样也可以
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
获取main方法并执行

6、通过反射运行配置文件内容

​ 利用反射和配置文件,可以使应用程序更新时,对源码无需进行修改,只需将类发送给客户端,修改配置文件即可

application.properties

classname=com.example.reflection.Student
methodName=test3

Student

package com.example.reflection;

public class Student {
    /**
     * 无参构造方法
     */
    public Student() {
        System.out.println("无参构造方法执行了...");
    }

    public void test1(String str) {
        System.out.println("调用了公有的、String参数的方法" + str + "...");
    }
}

测试类

public class Demo {
    public static void main(String[] args) {
         Properties prop = new Properties();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("application.properties");
        try {
            prop.load(is);
            //获取类
            String classname = prop.getProperty("classname");
            Class<?> clazz = Class.forName(classname);
            //获取方法名
            String methodName = prop.getProperty("methodName");
            Method test2 = clazz.getDeclaredMethod(methodName);
            test2.invoke(clazz.getConstructor().newInstance());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

运行结果:
通过反射运行配置文件内容

7、通过反射越过泛型检查

需求:有一个List list,向其中添加Integer类型的数据

测试类

public class Demo {
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        //获取ArrayList的Class对象,反向调用add()方法
        Class<? extends List> clazz = list.getClass();
        try {
            Method add = clazz.getMethod("add", Object.class);
            add.invoke(list, 13);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

运行结果:
通过反射越过泛型检查

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

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

相关文章

Xcode Developer Document 开发者文档

总目录 iOS开发笔记目录 从一无所知到入门 文章目录IntroDeveloper Documentation 打开方式菜单栏点击 &#xff5c; 快捷键方式另一种打开方式Intro 2016年我在学校学Java的时候&#xff0c;要查某个Java类/方法的用法还得自己手动下载一种.chm格式的开发文档文件&#xff0c…

python爬虫常见错误

python爬虫常见错误前言python常见错误1. AttributeError: WebDriver object has no attribute find_element_by_id1. 问题描述2. 解决办法2. selenium&#xff1a;DeprecationWarning: executable_path has been deprecated, please pass in1. 问题描述2. 解决办法3. 下载了包…

4、算法MATLAB---认识矩阵

认识矩阵1、矩阵定义和基本运算1.1 赋值运算符&#xff1a;1.2 等号运算符&#xff1a;1.3 空矩阵1.4 一行一列矩阵1.5 行矩阵&#xff08;元素用空格或逗号分隔&#xff09;1.6 列矩阵&#xff08;分号表示换行&#xff09;1.7 m行n列的矩阵&#xff1a;行值用逗号间隔&#x…

SPI总线设备驱动模型

SPI总线设备驱动模型 文章目录SPI总线设备驱动模型参考资料&#xff1a;一、平台总线设备驱动模型二、 数据结构2.1 SPI控制器数据结构2.2 SPI设备数据结构2.3 SPI设备驱动三、 SPI驱动框架3.1 SPI控制器驱动程序3.2 SPI设备驱动程序致谢参考资料&#xff1a; 内核头文件&…

角角的Qt自学日记:Qt的安装

目录 2. 打开下载器&#xff0c;输入账号和密码&#xff0c;然后单击下一步&#xff1a; 3. 分别单击2个单选框&#xff0c;其它不用管&#xff0c;直接单击下一步&#xff1a; 4. 先设置一下安装目录&#xff0c;因为现在Qt基本都好几个g&#xff0c;建议找个内存够的盘。然…

尝试用程序计算Π(3.141592653......)

文章目录1. π\piπ2. 用微积分来计算π\piπ2.1 原理2.2 代码2.3 结果2.4 分析1. π\piπ π\piπ的重要性或者地位不用多说&#xff0c;有时候还是很好奇&#xff0c;精确地π\piπ值是怎么计算出来的。研究π\piπ的精确计算应该是很多数学家计算机科学家努力的方向&#xf…

【老卫搬砖】034期:HarmonyOS 3.1 Beta 1初体验,我在本地模拟器里面刷短视频

今天啊打开这个DevEco Studio的话&#xff0c;已经提示有3.1Beta1版本的一个更新啊。然后看一下它的一些特性。本文也演示了如何在本地模拟器里面运行HarmonyOS版短视频。 主要特性 新特性包括&#xff1a; Added support for Windows 11 64-bit and macOS 13.x OSs, as well…

vue中render函数的作用和参数(vue2中render函数用法)

render 函数是 Vue2.x 新增的一个函数、主要用来提升节点的性能&#xff0c;它是基于 JavaScript 计算。使用 Render 函数将 Template 里面的节点解析成虚拟的 Dom 。Vue 推荐在绝大多数情况下使用模板来创建 HTML。然而在一些场景中&#xff0c;需要 JavaScript 的完全编程能力…

RK3568平台开发系列讲解(驱动基础篇)GIC v3中断控制器

🚀返回专栏总目录 文章目录 一、什么是GIC二、GIC v3中断类型三、GIC v3基本结构3.1、Distributor3.2、CPU interface简介3.3、Redistributor简介3.4、ITS(Interrupt translation service)4、中断状态和处理流程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢ARM多核…

在线文档技术-编辑器篇

这是在线文档技术的第二篇文章&#xff0c;本文将对目前市面上所有的主流编辑器和在线文档进行一次深入的剖析和研究&#xff0c;从而使大家对在线文档技术有更深入的了解&#xff0c;也让更多人能够参与其开发与设计中来。 注意&#xff1a;出于对主流文档产品的尊重&#xf…

【Linux环境配置】7. Linux部署code-server

安装 code-server 两种方法&#xff0c;一种是在线安装&#xff0c;另一种是本地安装。因为主机访问github可能会报443错误&#xff0c;因此这里我推荐使用本地安装方法&#xff01; 本地安装方法 进入github&#xff0c;搜索code-server找到项目地址&#xff1a;https://gi…

链表(一):移除链表元素、设计链表等力扣经典链表题目

203.移除链表元素相关题目链接&#xff1a;力扣 - 移除链表元素题目重现给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。思路链表的删除操作如上图所示&#xff0c;我们需要先找到要删除的…

不需要高深技术,只需要Python:创建一个可定制的HTTP服务器!

目录 1、编写服务端代码,命名为httpserver.py文件。 2、编写网页htmlcss文件&#xff0c;命名为index.html和style.css文件。 3、复制htmlcss到服务端py文件同一文件夹下。 4、运行服务端程序。 5、浏览器中输入localhost:8080显示如下&#xff1a; 要编写一个简单的能发布…

UML类图中的类图、接口图、关联、聚合、依赖、组合概念的解释

文章目录UML类图依赖和关联的主要区别UML类图 类&#xff1a;类有三层结构 第一层&#xff1a;类的名字第二层&#xff1a;类的属性第三层&#xff1a;类的方法 接口&#xff1a;接口跟类相似&#xff0c;不过多了一个<<interface>>来表示它是一个接口 第一层&a…

华为OD机试用Python实现 -【统一限载货物数最小值】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲统一限载货物数最小值题目描述输入描述输出描述说明示例一输入输出说明示例二输入输出说明Python 代码实现算法逻辑华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查…

社畜大学生的Python之pandas学习笔记,保姆入门级教学

接上期&#xff0c;上篇介绍了 NumPy&#xff0c;本篇介绍 pandas。 目录 pandas 入门pandas 的数据结构介绍基本功能汇总和计算描述统计处理缺失数据层次化索引 pandas 入门 Pandas 是基于 Numpy 构建的&#xff0c;让以 NumPy 为中心的应用变的更加简单。 Pandas是基于Numpy…

【20230225】【剑指1】分治算法(中等)

1.重建二叉树class Solution { public:TreeNode* traversal(vector<int>& preorder,vector<int>& inorder){if(preorder.size()0) return NULL;int rootValuepreorder.front();TreeNode* rootnew TreeNode(rootValue);//int rootValuepreorder[0];if(preo…

Java学习--多线程(等待唤醒机制)生产者消费者

3.生产者消费者 3.1生产者和消费者模式概述【应用】 概述 生产者消费者模式是一个十分经典的多线程协作的模式&#xff0c;弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻。 所谓生产者消费者问题&#xff0c;实际上主要是包含了两类线程&#xff1a; ​ 一类是生…

C++ primer 之 extern

C primer 之 extern什么是声明什么是定义两者有什么区别ertern的作用什么是声明 就是使得名字为程序所知&#xff0c;一个文件如果想使用别处定义的名字就必须包含对那个名字的声明。 什么是定义 负责创建与名字关联的实体。 两者有什么区别 变量声明和声明都规定了变量的…

FPGA纯verilog解码SDI视频 纯逻辑资源实现 提供2套工程源码和技术支持

目录1、前言2、硬件电路解析SDI摄像头Gv8601a单端转差GTX解串SDI解码VGA时序恢复YUV转RGB图像输出FDMA图像缓存HDMI输出3、工程1详解&#xff1a;无缓存输出4、工程2详解&#xff1a;缓存3帧输出5、上板调试验证并演示6、福利&#xff1a;工程代码的获取1、前言 FPGA实现SDI视…