Java#37(反射)

news2024/11/29 0:37:23

目录

一.反射的作用和关键

二. 反射获取对象

1.反射获取类对象

2.反射获取构造器对象 

3.反射获取成员变量对象

4. 反射获取方法对象

5.用反射绕过编译阶段为集合添加数据

反射做通用框架


一.反射的作用和关键

作用: 反射是在运行时获取类的字节码文件对象: 然后可以解析类中的全部成分
关键: 反射的核心思想和关键就是:得到编译以后的class文件对象

二. 反射获取对象

1.反射获取类对象

(1)使用 Class类中的静态方法

(2)使用 类名.class

(3)使用 对象.getClass( )

代码示范: 

package com.guaiwu;

public class Test1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //1.Class中forName(全限名:包名+类名)
        Class c = Class.forName("com.guaiwu.Student");
        System.out.println(c);
        //2.类名.class
        Class c1 = Student.class;
        System.out.println(c1);
        //3.对象.getClass()
        Student stu = new Student();
        Class c2 = stu.getClass();
        System.out.println(c2);
    }
}

结果展示: 

2.反射获取构造器对象 

使用反射技术获取构造器对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象

反射得到的构造器可以做什么?
依然可以创建对象
public newlnstance(Object... initargs)

如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
setAccessible(boolean)
反射可以破坏封装性,私有的也可以执行了
Class类中用于获取构造器的方法
                                        方法
Constructor<?>[ ] getConstructors()    返回所有构造器对象的数组 (只能拿public的)
Constructor<?>[ ] getDeclaredConstructors()返回所有构造器对象的数组,存在就能拿到
Constructor<T> getConstructor(Class<?>...parameterTypes)    返回单个构造器对象 (只能拿public的)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)    返回单个构造器对象,存在就能拿到
代码示范:  第一段是测试类, 第二段是Student类

package com.guaiwu;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLOutput;

public class TestStudent {

    @Test
    public void getDeclaredConstructors(){
        Class c1 = Student.class;
        System.out.println(c1);
        //getConstructor()和getDeclaredConstructor()的使用
        // Constructor con = c1.getConstructor();只能那public(比较局限)
        Constructor[] con1 = c1.getDeclaredConstructors();
        for (Constructor constructor : con1) {
            //构造方法的名字           参数数量
            System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());
        }
        System.out.println("=====================");
    }
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c2 = Student.class;
        System.out.println(c2);
        //getConstructor()和getDeclaredConstructor()的使用
        //Constructor dcon = c2.getConstructor(String.class, int.class);只能那public(比较局限)
        Constructor dcon1 = c2.getDeclaredConstructor(String.class, int.class);
        System.out.println(dcon1.getName()+"--->"+dcon1.getParameterCount());
        //因为Student的有参构造是private,所以要先打开权限
        dcon1.setAccessible(true);
        //newInstance的返回类型是Object,所以要强转
        Student stu = (Student) dcon1.newInstance("张三", 90);
        System.out.println(stu);
    }
}
package com.guaiwu;

public class Student {
    private String name;
    private int age;

    private Student() {
    }
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

结果展示: 

3.反射获取成员变量对象

使用反射技术获取成员变量对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员变量的方法
                  方法                                                                   说明
Field[ ] getFields()                           返回所有成员变量对象的数组 (只能拿public的)
Fieldl getDeclaredFields()                 返回所有成员变量对象的数组,存在就能拿到
Field getField(String name)                   返回单个成员变量对象 (只能拿public的)
Field getDeclaredField(String name)     返回单个成员变量对象,存在就能拿到
Field类中用于取值、赋值的方法
void set(Object obj, Object value):          赋值
Object get(Object obj)                              获取值

代码示范:  第一段是测试类, 第二段是Student类

package com.guaiwu;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class TestStudent {

    /*@Test
    public void getDeclaredConstructors(){
        Class c1 = Student.class;
        System.out.println(c1);
        //getConstructor()和getDeclaredConstructor()的使用
        // Constructor con = c1.getConstructor();只能那public(比较局限)
        Constructor[] con1 = c1.getDeclaredConstructors();
        for (Constructor constructor : con1) {
            //构造方法的名字           参数数量
            System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());
        }
        System.out.println("=====================");
    }
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class c2 = Student.class;
        System.out.println(c2);
        //getConstructor()和getDeclaredConstructor()的使用
        //Constructor dcon = c2.getConstructor(String.class, int.class);只能那public(比较局限)
        Constructor dcon1 = c2.getDeclaredConstructor(String.class, int.class);
        System.out.println(dcon1.getName()+"--->"+dcon1.getParameterCount());
        //因为Student的有参构造是private,所以要先打开权限
        dcon1.setAccessible(true);
        //newInstance的返回类型是Object,所以要强转
        Student stu = (Student) dcon1.newInstance("张三", 90);
        System.out.println(stu);
        System.out.println("=====================");
    }*/
    @Test
    public void getDeclaredFields(){
        //getFields()和getDeclaredFields()的使用
        //获取全部成员变量
        Class c3 = Student.class;
        Field[] DF = c3.getDeclaredFields();
        System.out.println(DF);
        for (Field field : DF) {
            System.out.println(field.getName()+"--->"+field.getType());
        }
        System.out.println("=====================");
    }
    @Test
    public void getDeclaredField() throws NoSuchFieldException, IllegalAccessException {
        Class c4 = Student.class;//获取类对象
        Field fieldName = c4.getDeclaredField("name");//获取某个成员变量
        //暴力打开权限
        fieldName.setAccessible(true);
        //获取一个Student类的对象
        Student stu = new Student();
        //使用set()方法
        fieldName.set(stu,"李四");
        String str = (String) fieldName.get(stu);
        System.out.println(str);
        System.out.println("=====================");
    }
}
package com.guaiwu;

public class Student {
    private String name;
    private int age;

    public Student() {
    }
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

结果展示: 

4. 反射获取方法对象

使用反射技术获取方法对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员方法的方法
                      方法                                                  
Method[] getMethods()     返回所有成员方法对象的数组 (只能拿public的)
Method[] getDeclaredMethods()    返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name,Class<?>...parameterTypes)    返回单个成员方法对象 (只能拿public的)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)      返回单个成员方法对象,存在就能拿到

Method类中用于触发执行的方法
                运行方法

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

代码示范: 

package com.guaiwu;

public class Student {
    private String name;
    private int age;

    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}
package com.guaiwu;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestStudent {

    @Test
    public void getDeclaredMethods(){
        Class c5 = Student.class;
        Method[] mt1 = c5.getDeclaredMethods();
        for (Method method : mt1) {
            System.out.println(method.getName());
        }
        System.out.println("=====================");
    }
    @Test
    public void getDeclaredMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class c6 = Student.class;
        Method ts = c6.getDeclaredMethod("setName", String.class);
        ts.setAccessible(true);
        Student stu = new Student("wangwu",66);

        Object result = ts.invoke(stu,"maliu");
        System.out.println(result);
        System.out.println("=====================");
    }
}

结果示范: 

5.用反射绕过编译阶段为集合添加数据

原理: 编译成Class文件进入运行阶段的时候, 泛型会自动擦除

         反射是作用在运行时的技术, 此时已经不存在泛型了

代码示范: 

package com.guaiwu;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(123);
        list1.add(234);
        list1.add(345);
        //list1.add("加字符串会报错");
        //得到Class对象
        Class c1 = list1.getClass();
        //getDeclaredMethod获取对应的方法
        Method add1 = c1.getDeclaredMethod("add", Object.class);
        //通过invoke执行方法
        //另一种方式
        add1.invoke(list1,"现在可以加任意类型");
        System.out.println(list1);
        ArrayList list2 = list1;
        list2.add("ture");
        System.out.println(list1);
    }
}

结果展示: 

 

反射做通用框架

练习: 给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文件中去

代码示范: 第一,第二段是类的代码, 第三段是通用框架的代码(重点), 第四段是测试代码

package com.guaiwu;

public class Teacher {
    private String name;
    private int age;
    private String schoolName;
    private String hobby;

    public Teacher() {
    }

    public Teacher(String name, int age, String schoolName, String hobby) {
        this.name = name;
        this.age = age;
        this.schoolName = schoolName;
        this.hobby = hobby;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return schoolName
     */
    public String getSchoolName() {
        return schoolName;
    }

    /**
     * 设置
     * @param schoolName
     */
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    /**
     * 获取
     * @return hobby
     */
    public String getHobby() {
        return hobby;
    }

    /**
     * 设置
     * @param hobby
     */
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public String toString() {
        return "Teacher{name = " + name + ", age = " + age + ", schoolName = " + schoolName + ", hobby = " + hobby + "}";
    }
}
package com.guaiwu;

public class Student {
    private String name;
    private int age;
    private String schoolName;
    private String hobby;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return schoolName
     */
    public String getSchoolName() {
        return schoolName;
    }

    /**
     * 设置
     * @param schoolName
     */
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }

    /**
     * 获取
     * @return hobby
     */
    public String getHobby() {
        return hobby;
    }

    /**
     * 设置
     * @param hobby
     */
    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", schoolName = " + schoolName + ", hobby = " + hobby + "}";
    }
}
package com.guaiwu;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class MybatisUtil {
    //保存任意类型的对象
    public static void save(Object obj) throws IllegalAccessException, FileNotFoundException {
        PrintStream ps = new PrintStream(new FileOutputStream("D:\\Java\\java\\Demo1_12_14\\src\\com\\guaiwu\\a.txt",true));
        //得到类对象
        Class c1 = obj.getClass();
        ps.println("========="+c1.getSimpleName()+"=========");
        //得到类的全部成员变量
        Field[] fields = c1.getDeclaredFields();
        //遍历集合
        for (Field field : fields) {
            String name = field.getName();
            //取值
            field.setAccessible(true);//打开权限
            String value = field.get(obj) + "";
            ps.println(name+"="+value);
        }
    }
}
package com.guaiwu;

import java.io.FileNotFoundException;

public class Demo1 {
    public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {
        Student stu = new Student("张三",66,"小学","睡觉");
        Teacher tea = new Teacher("李四",99,"小学","打羽毛球");
        MybatisUtil.save(stu);
        MybatisUtil.save(tea);
    }
}

结果展示: 

 

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

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

相关文章

未能加载文件或程序集XXX.dll,程序启动失败的解决方案

之前在VS2019上下载一个项目&#xff0c;运行后就报错&#xff0c;弹出 出错&#xff1a;未能加载文件或程序集XXX.dll 我们选中该dll&#xff0c;右键&#xff0c;属性&#xff0c;发现 该dll被锁定 点击“解决锁定”即可解决。 为了一劳永逸解决此问题&#xff0c;后到微软…

【头歌C语言程序与设计】结构体共用体枚举类型

目录 写在前面 正文 第1关&#xff1a;结构体 第2关&#xff1a;共用体 第3关&#xff1a;枚举类型 写在最后 写在前面 本文代码是我自己所作&#xff0c;本人水平有限&#xff0c;可能部分代码看着不够简练&#xff0c;运行效率不高,但都能运行成功。另外&#xff0c;如…

C++ 智能指针

目录 为什么需要智能指针&#xff1f; RAII 智能指针的原理 C智能指针的历史 智能指针 auto_ptr unique_ptr shared_ptr shared_ptr 引用计数解决智能指针拷贝问题 shared_ptr 循环引用问题 智能指针删除器 weak_ptr 为什么需要智能指针&#xff1f; 1. 我们在很多…

基于 SSM 的 CRM 客户管理系统

1&#xff1a;通过点击【登录】按钮&#xff0c;获取登录的接口地址 2&#xff1a;在UserLoginController类中&#xff0c;增加登录接口 3&#xff1a;首先判断用户名是否存在&#xff0c;其次判断匹配是否匹配 4&#xff1a;处理session问题 代码如下&#xff1a; UserLo…

java计算机毕业设计ssm智能会议室管理系统0v396(附源码、数据库)

java计算机毕业设计ssm智能会议室管理系统0v396&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xf…

TAPD新增需求自动通知飞书

【实现效果&#xff1a;】TAPD新增需求/缺陷&#xff0c;可以自动通知飞书机器人并通知相关人员&#xff0c;让相关人员可以及时关注到新增需求/缺陷并及时处理。 【流程配置】 第一步&#xff1a;打开腾讯云HiFlow模版中心&#xff0c;搜索打开“TAPD需求/项目更新实时通知飞…

C# !(null包容)运算符的使用

总目录 文章目录总目录前言一、!(null包容&#xff09;运算符是什么&#xff1f;二、!(null包容&#xff09;运算符如何使用&#xff1f;1.使用2.扩展-预处理器指令启用或关闭null检查总结前言 本文主要讲解&#xff01;&#xff08;null包容&#xff09;运算符的使用&#xf…

艾美捷科研专用西妥昔单抗Cetuximab相关介绍

西妥昔单抗&#xff08;Cetuximab&#xff09;&#xff0c;商品名尔必得舒&#xff08;Erbitux&#xff09;&#xff0c;是美商英克隆公司和美商百时美施贵宝的专-利药。西妥昔单抗是一种对抗表皮生长因子受体&#xff08;EGFR&#xff09;的单克隆抗体&#xff0c;经美国食品药…

MySQL表的增删查改(下)

作者&#xff1a;~小明学编程 文章专栏&#xff1a;MySQL 格言&#xff1a;目之所及皆为回忆&#xff0c;心之所想皆为过往 今天给大家分享的是增删查改中的一些比较核心的东西同时也是难点&#xff0c;希望能给大家带来一些帮助吧。 目录 数据库的约束 NULL约束 Unique的…

数据结构C语言版 —— 顺序表增删改查实现

文章目录顺序表1. 线性表2. 顺序表3. 顺序表基本概念4. 顺序表实现顺序表初始化顺序表的扩容顺序表的插入顺序表的删除顺序表的查找顺序表的修改顺序表的销毁5. 顺序表总结顺序表 1. 线性表 线性表&#xff1a;线性表是由n个具有相同特性的数据元素组成的序列。线性表是一种在…

【DevOps】总结下容器方式构建Grafana-reporter生成PDF格式报告

目录 Grafana-reporter1、编写Dockerfile2、构建镜像3、运行Grafana-reporter4、在Grafana配置Link即文章:【DevOps】Prometheus+Grafana:生成pdf报表总结下Grafana-reporter镜像打包过程 最终pdf实现效果类似: Grafana-reporter 简介:“A simple http service that gen…

[附源码]Python计算机毕业设计仿咸鱼二手物品交易系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

TCP/IP 网络原理【TCP篇】

&#x1f389;&#x1f389;&#x1f389;写在前面&#xff1a; 博主主页&#xff1a;&#x1f339;&#x1f339;&#x1f339;戳一戳&#xff0c;欢迎大佬指点&#xff01; 目标梦想&#xff1a;进大厂&#xff0c;立志成为一个牛掰的Java程序猿&#xff0c;虽然现在还是一个…

joinquant量化是什么?是主流的量化平台吗?

joinquant量化是什么&#xff1f;我们做量化投资的时候&#xff0c;目前比较流行的平台&#xff0c;我推荐的是这三个&#xff0c;一个是Ricequant&#xff0c;另外一个是JoinQuant&#xff0c;还有一个QUANTOPIAN&#xff0c;国内实际上就是优矿。这几个现在比较流行&#xff…

git分支管理

分支管理&#xff08;拙见&#xff09; 1&#xff0c;首先master分支是最高级别分支。不可编辑 2&#xff0c;创建一个release分支&#xff0c;从master上拉取&#xff0c;用于上线分支 3&#xff0c;创建dev开发分支&#xff0c;从relase分支拉取&#xff0c;如果有开发环境…

裸辞美团花两月吃透这 Java 岗 798 道真题解析,定级阿里 P7

2023 的面试即将到来&#xff0c;大家准备的怎么样了呢&#xff1f;你有没有正在为此而发愁呢&#xff1f;那么一起来看看小编整理的这富含的 15 个互联网大厂 Java 高级工程师核心面试问题整理吧&#xff01;已助我在 2023 年的金三银四跳槽季中拿到阿里 P7. 内容包括&#x…

Stm32旧版库函数9——ADC读取电压值

#include <stm32f10x_lib.h> #include "adc.h" unsigned char i0; u16 ad[3]{0,0,0}; //初始化ADC //这里我们仅以规则通道为例 void Adc_init(void) { //先初始化…

Unity - Baking System - 烘焙失效的问题

文章目录环境问题解决方法环境 unity : 2020.2.5f1, 2020.3.37f1 pipeline : BRP 问题 我之前有去搜索过场景烘焙失效的问题&#xff0c;都是 unity 发包后和 unity Editor 下运行不同&#xff1a;发包后丢失 烘焙效果&#xff0c;一般都是说&#xff1a;shader 中的 Lightma…

【Hive】分隔符 『 单字节分隔符 | 多字节分隔符』

文章目录1. 概述2. 单字节分隔符方法&#xff1a;使用delimited关键字3. 其它复杂情况方式一&#xff1a;写MR程序进行字符替换转为单字节分隔符问题&#xff08;不推荐&#xff09;方式二&#xff1a;自定义InputFormat转为单字节分隔符问题&#xff08;不推荐&#xff09;方式…

矩阵

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 车车的爱之矩阵是一个行数为 n&#xff0c;列数为 m 的矩阵并满足以下条件: 111. 矩阵元素 xij​ 为整数并满足 0<∣xij​∣⩽114514。 222. 对于在矩阵边界的元素&#xff0c;即 iii 为 1 或…