《Java-SE-第三十七章》之反射

news2024/11/24 10:28:56

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


文章目录

  • 反射
    • 定义
    • 基本使用
      • 获取类
      • 获取构造器
      • 获取成员变量
      • 获取成员方法
      • 使用场景


反射

定义

Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然都可以拿到,我们就可以修改类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

基本使用

获取类

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的。因为对象都是通过类创建而来的,拿到了Class对象,并对其解析就可以获取类的成员属性,成员方法,构造器。Class对象存在的位置具体如下图。

在这里插入图片描述

获取类有三种方法

  1. 使用 Class.forName(“类的全路径名”); 静态方法。
  2. 使用类名.class
  3. 使用对象.getClass();

使用演示

首先创建一个User类,便于后期使用

@Data
@AllArgsConstructor
@NoArgsConstructor

public class User {
    private String username;
    private String password;
    public int age ;


    public  String pr(String username){
      return username;
    }
}

开始使用上述三种方法获取User的类对象

public class ClassDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> user = Class.forName("org.example.Functional.model.User");
        Class<User> userClass = User.class;
        User user2 = new User("user2", "11");
        Class<? extends User> aClass = user2.getClass();
        System.out.println(user);
        System.out.println(userClass);
        System.out.println(aClass);
    }
}

获取构造器

获取构造器的方法如下

方法说明
Constructor<?>[] getConstructors()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[] getDeclaredConstructors()返回所有构造器对象的数组,存在就能拿到
Constructor getConstructor(Class<?>… parameterTypes)返回单个构造器对象(只能拿public的)
Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造器对象,存在就能拿到

使用演示

import java.lang.reflect.Constructor;

public class ConstructorsDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的无参构造
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        //设置禁止访问权限
        declaredConstructor.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor.getName()+"->"+declaredConstructor.getParameterCount());
        //获取有参构造
        Constructor<User> declaredConstructor1 = userClass.getConstructor(String.class, String.class);
        //设置禁止访问权限
        declaredConstructor1.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor1.getName()+"->"+declaredConstructor1.getParameterCount());

        Constructor<?>[] constructors = userClass.getConstructors();
        Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
        System.out.println(constructors[1]);
        System.out.println(constructors[0]);
        System.out.println(declaredConstructors[1]);
        System.out.println(declaredConstructors[0]);
    }
}

运行结果:

在这里插入图片描述

获取构造器的作用依旧是为了初始化对象返回

Constructor类中用于创建对象的方法

方法说明
T newInstance(Object… initargs)根据指定的构造器创建对象
public void setAccessible(boolean flag)设置为true,表示取消访问检查,进行暴力反射

使用演示

将User的有参构造设置为私有,并且不设置访问检查

public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

在这里插入图片描述

取消访问检查后

public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        //设置禁止访问权限
         declaredConstructor1.setAccessible(true);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

在这里插入图片描述

如果是非public的构造器,需要打开权限,然后才能创建对象。反射是Java的后门破坏的封装性,私有的也可以构造方法也可以执行了。

获取成员变量

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

方法说明
Field[] getFields()返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields()返回所有成员变量对象的数组,存在就能拿到
Field getField(String name)返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name)返回单个成员变量对象,存在就能拿到

使用演示

public class AttributeDemo {
    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Field[] fields = userClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName()+"-->"+field.getType());
        }
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName()+"-->"+declaredField.getType());
        }
        //定位某个变量
        Field age = userClass.getField("age");
        Field username = userClass.getDeclaredField("username");
        Field password = userClass.getDeclaredField("password");
        User user = new User();
        //设置私有变量的访问
        username.setAccessible(true);
        password.setAccessible(true);
        //赋值
        username.set(user,"sdf");
        password.set(user,"ss12");
        age.set(user,90);
        System.out.println(user);
        //取值
        String o = (String)username.get(user);
        System.out.println(o);
    }
}

运行结果:

在这里插入图片描述

私有的成员变量依旧需要开启访问权限

获取成员方法

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

方法说明
Method[] getMethods()返回所有成员方法对象的数组(只能拿public的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象,存在就能拿到

使用演示

public class MethodDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的成员方法
        Method[] methods = userClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + " "+method.getParameterCount()
            +method.getReturnType());
        }
        //获取某个对象方法
        Method pr = userClass.getDeclaredMethod("pr",String.class);
        System.out.println(pr.getName() + " "+pr.getParameterCount()+" "
                +pr.getReturnType());
        User user = new User();
        pr.setAccessible(true);
        //调用方法,用user对象
        Object invoke = pr.invoke(user,"java");
        System.out.println(invoke);
    }
}

使用场景

  1. 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统****应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。

  2. 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。


各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

在这里插入图片描述

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

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

相关文章

【Vue-Router】嵌套路由

footer.vue <template><div><router-view></router-view><hr><h1>我是父路由</h1><div><router-link to"/user">Login</router-link><router-link to"/user/reg" style"margin-left…

Selenium 测试用例编写

编写Selenium测试用例就是模拟用户在浏览器上的一系列操作&#xff0c;通过脚本来完成自动化测试。 编写测试用例的优势&#xff1a; 开源&#xff0c;免费。 支持多种浏览器 IE&#xff0c;Firefox&#xff0c;Chrome&#xff0c;Safari。 支持多平台 Windows&#xff0c;Li…

【C语言】const修饰普通变量和指针

大家好&#xff0c;我是苏貝&#xff0c;本篇博客是系列博客每日一题的第一篇&#xff0c;本系列的题都不会太难&#xff0c;如果大家对这种系列的博客感兴趣的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 文章目录 一.const修饰普通变量二.const修饰指…

Spring事务控制

目录 1、什么是事务控制 2、编程式事务控制 2.1、简介 2.2、相关对象 2.2.1、PlatformTransactionManager 2.2.2、TransactionDefinition 2.2.2.1、事务隔离级别 2.2.2.2、事务传播行为 2.2.3、TransactionStatus 3、声明式事务控制 3.1、简介 3.2、区别 3.3、⭐作…

Unity实现异步加载场景

一&#xff1a;创建UGUI 首先我们在LoginCanvas登入面板下面创建一个Panel,取名为LoadScreen,再在loadScreen下面创建一个Image组件&#xff0c;放置背景图片&#xff0c;然后我们再在lpadScreen下面继续创建一个Slider,这个是用来加载进度条的&#xff0c;我们改名为LoadSlid…

【考研数学】概率论与数理统计 | 第一章——随机事件与概率(1)

文章目录 一、随机试验与随机事件1.1 随机试验1.2 样本空间1.3 随机事件 二、事件的运算与关系2.1 事件的运算2.2 事件的关系2.3 事件运算的性质 三、概率的公理化定义与概率的基本性质3.1 概率的公理化定义3.2 概率的基本性质 写在最后 一、随机试验与随机事件 1.1 随机试验 …

Docker-使用数据卷、文件挂载进行数据存储与共享

一、前言 默认情况下&#xff0c;在Docker容器内创建的所有文件都只能在容器内部使用。容器删除后&#xff0c;数据也跟着删除&#xff0c;虽然通常我们不会删除容器&#xff0c;但是一旦宿主机发生故障&#xff0c;我们重新创建容器恢复服务&#xff0c;那么之前容器创建的文…

Matlab图坐标轴数值负号改为减号(change the hyphen (-) into minus sign (−, “U+2212”))

在MATLAB中&#xff0c;坐标轴负数默认符号是 - &#xff0c;如下图所示 x 1:1:50; y sin(x); plot(x,y)可通过以下两语句将负号修改为减号&#xff1a; set(gca,defaultAxesTickLabelInterpreter,latex); yticklabels(strrep(yticklabels,-,$-$));或者 set(gca, TickLabe…

安装mmcv失败

安装mmcv时报错 pip install mmcv这里只需要按照提示升级一下pip就可以了 pip install --upgrade pip然后安装成功

OCT介绍和分类

前言&#xff1a;研究方向和OCT有关&#xff0c;为了方便以后回顾&#xff0c;所以整理了OCT相关的一些内容。 OCT介绍和分类 OCT介绍分类时域OCT频域OCT扫频OCT谱域OCT OCT介绍 名称&#xff1a;OCT、光学相干层析成像术、Optical Coherence Tomography。 概念&#xff1a;O…

添加vue devtools扩展工具+添加后F12不显示Vue图标

前言&#xff1a;在开启Vue学习之旅时&#xff0c;遇到问题两个问题&#xff0c;第一添加不上vue devtools扩展工具&#xff0c;第二添加完成后&#xff0c;F12不显示Vue图标。查阅了很多博客&#xff0c;自己解决了问题&#xff0c;故写此博客记录。如果你遇到和我一样的问题&…

Docker容器与虚拟化技术:Docker架构、镜像管理

目录 一、理论 1.Doker概述 2.Docker核心概念 3.Docker安装 4.Docker的镜像管理命令 二、实验 1.Docker安装 2.查看Docker信息 3.Docker的镜像管理命令 三、问题 1.如何注册Docker账号 2.如何设置Docker公共存储库 四、总结 一、理论 1.Doker概述 (1) IT架构 裸…

request发送http请求

今天正式开始为大家介绍接口自动化&#xff0c;相信很多做测试的朋友&#xff0c;都用过一些工具&#xff0c;比如jmeter&#xff0c;loadrunner&#xff0c;postman等等&#xff0c;所以今天先给那些基础不太好的同学&#xff0c;先讲讲postman如何来测接口以及如何用pthon代码…

T113-S3 Tina-Linux -- 2.开发板使用

1. 硬件环境 1.1 开发板 型号&#xff1a;100ASK_T113-PRO Base V1.1&#xff08;韦东山&#xff09;配置&#xff1a;CPU&#xff1a;T113-S3&#xff0c;RAM&#xff1a;128MB&#xff0c;ROM&#xff1a;128MB 2. 各模块使用 2.1 wifi wifi模组型号&#xff1a;XR829…

数学建模(三)整数规划

视频推荐&#xff1a;B站_数学建模老哥 一、整数规划基本原理 数学规划中的变量&#xff08;部分或全部&#xff09;限制为整数时&#xff0c;称为整数规划。若在线性规划模型中&#xff0c;变量限制为整数&#xff0c;则称为整数线性规划。目前所流行的求解整数规划的方法&am…

C语言刷题训练【第11天】

大家好&#xff0c;我是纪宁。 今天是C语言笔试刷题训练的第11天&#xff0c;加油&#xff01; 文章目录 1、声明以下变量&#xff0c;则表达式: ch/i (f*d – i) 的结果类型为&#xff08; &#xff09;2、关于代码的说法正确的是&#xff08; &#xff09;3、已知有如下各变…

微PE工具箱实现U盘重装Windows系统

教程来源 U盘重装Windows系统&#xff08;微PE工具箱&#xff09;_哔哩哔哩_bilibili 加上自己的一丢丢理解&#xff0c;如果你觉得长视频看了犯困&#xff0c;不如看看我的理解文章说不定能够帮助到你 准备工作 到这个网站使用迅雷下载免费无插件的官方镜像MSDN, 我告诉你…

DAY05_SpringMVC—SSM整合表现层数据封装异常处理器项目异常处理方案SSM整合页面开发拦截器

目录 一 SSM整合1 SSM整合配置问题导入1.1 SSM整合流程1.2 SSM整合配置1.2.1 创建工程&#xff0c;添加依赖和插件1.2.2 Spring整合Mybatis1.2.3 Spring整合SpringMVC 2 功能模块开发2.1 数据层开发(BookDao)2.2 业务层开发(BookService/BookServiceImpl)2.3 表现层开发(BookCo…

vue+flask基于知识图谱的抑郁症问答系统

vueflask基于知识图谱的抑郁症问答系统 抑郁症已经成为当今社会刻不容缓需要解决的问题&#xff0c;抑郁症的危害主要有以下几种&#xff1a;1.可导致病人情绪低落&#xff1a;抑郁症的病人长期处于悲观的状态中&#xff0c;感觉不到快乐&#xff0c;总是高兴不起来。2.可导致工…