Java基础-反射

2023-11-01

反射的基本作用、关键?

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

反射的第一步:获取Class类对象,如此才可以解析类的全部成分

获取Class类的对象的三种方式

/**
 * 目标:反射第一步:获取class对象
 */
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1. Class类中的一个静态方法:forName(全限定名:包名 + 类名)
        Class clz = Class.forName("per.mjn.reflect.Student");
        System.out.println(clz);

        // 2. 类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        // 3. 对象.getClass()获取对象对应类的Class对象
        Student stu = new Student();
        Class c2 = stu.getClass();
        System.out.println(c2);
    }
}

 使用反射技术获取构造器对象并使用

  • 反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
  • Class类中用于获取构造器的方法
  1. Constructor<?>[] getConstructors()        返回所有构造器对象的数组(只能拿public的)
  2. Constructor<?>[] getDeclaredConstructors()    返回所有构造器对象的数组,存在就能拿到
  3. Constructor<?>[] getConstructor(Class<?>... parameterTypes)  返回单个构造器对象(只能拿public的)
  4. Constructor<?>[] getDeclaredConstructor(Class<?>... parameterTypes)  返回单个构造器对象,存在就能拿到
public class TestStudent01 {

    @Test
    public void getConstructors() {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的全部构造器对象(只能拿public)
        Constructor[] constructors = c.getConstructors();

        // c. 遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }
    }

    @Test
    public void getDeclaredConstructors() {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的全部构造器对象
        Constructor[] constructors = c.getDeclaredConstructors();

        // c. 遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "===>" + constructor.getParameterCount());
        }
    }

    @Test
    public void getConstructor() throws NoSuchMethodException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器,只能拿public修饰的构造器)
        Constructor constructor = c.getConstructor();

        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());
    }

    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器)
        Constructor constructor = c.getDeclaredConstructor();

        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());


        // c. 定位某个有参构造器
        Constructor constructor1 = c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1.getName() + "==>" + constructor1.getParameterCount());
    }
}

使用反射技术获取构造器对象并使用

  • 获取构造器的作用依然是初始化一个对象返回。

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

  1. T newInstance(Object... initargs)       根据指定的构造器创建对象
  2. public void setAccessible(boolean flag)    设置为true,表示取消访问检查,进行暴力反射
public class TestStudentDemo2 {
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // a. 获取类对象
        Class c = Student.class;

        // b. 提取类中的单个构造器对象(按照参数定位无参数构造器)
        Constructor constructor = c.getDeclaredConstructor();
        System.out.println(constructor.getName() + "==>" + constructor.getParameterCount());

        // 如果遇到了私有的构造器,可以暴力反射
        constructor.setAccessible(true);  // 权限被打开

        Student student = (Student) constructor.newInstance();
        System.out.println(student);

        // c. 定位某个有参构造器
        Constructor constructor1 = c.getDeclaredConstructor(String.class, int.class);
        System.out.println(constructor1.getName() + "==>" + constructor1.getParameterCount());

        Student student1 = (Student) constructor1.newInstance("孙悟空", 1000);
        System.out.println(student1);
    }
}
public class FieldDemo {

    /**
     * 获取全部成员变量
     */
    @Test
    public void getDeclaredFields() {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 定位全部成员变量
        Field[] fields = c.getDeclaredFields();
        // c. 遍历一下
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }

    /**
     * 获取某个成员变量
     */
    @Test
    public void getDeclaredField() throws NoSuchFieldException {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 根据名称定位某个成员变量
        Field f = c.getDeclaredField("age");
        System.out.println(f.getName() + "==>" + f.getType());
    }
}

给通过反射得到的成员变量赋值

@Test
    public void getDeclaredField() throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // a. 定位Class对象
        Class c = Student.class;
        // b. 根据名称定位某个成员变量
        Field agef = c.getDeclaredField("age");
        agef.setAccessible(true);

        Constructor constructor = c.getDeclaredConstructor();

        // c. 赋值
        Student s = (Student) constructor.newInstance();
        agef.set(s, 18);
        System.out.println(s);

        // d. 取值
        int age = (int) agef.get(s);
        System.out.println(age);
    }

总结:

1、利用反射技术获取成员变量的方式

  • 获取类中成员变量对象的方法
  • getDeclaredFields()
  • getDeclaredField(String name)

2、反射得到成员变量可以做什么?

  • 依然是在某个对象中取值和赋值。
  • void set(Object obj, Object value)
  • Object get(Object obj)
  • 如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
  • setAccessible(boolean)

获取类中的全部成员方法对象

@Test
    public void getDeclaredMethods() {
        // a. 获取类对象
        Class c = Student.class;
        // b. 提取全部方法,包括私有的
        Method[] methods = c.getDeclaredMethods();
        // c. 遍历全部方法
        for (Method method : methods) {
            System.out.println(method.getName() + "返回值类型:" + method.getReturnType() + " 参数个数:" + method.getParameterCount());
        }
    }

通过反射调用方法

@Test
    public void getDeclaredMethod() throws Exception {
        // a. 获取类对象
        Class c = Student.class;
        // b. 提取单个方法对象
        Method m = c.getDeclaredMethod("setName", String.class);

        // 暴力打开权限
        m.setAccessible(true);

        // c. 触发方法执行
        Student student = new Student();
        // 注意:如果方法是没有结果回来的,那么返回的是null
        Object result = m.invoke(student, "dog");
        System.out.println(result);
    }

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java基础-反射 的相关文章

随机推荐

  • 秋招-数据结构-二叉树篇

    秋招 数据结构 二叉树篇 介绍 基本信息 二叉树是n个有限元素的集合 该集合或者为空 或者由一个称为根 root 的元素及两个不相交的 被分别称为左子树和右子树的二叉树组成 是有序树 当集合为空时 称该二叉树为空二叉树 优缺点 顺序存储可能
  • linux ftp 未找到命令,Linux不能使用FTP 命令 -bash: ftp: command not found

    Linux下登陆 Linux中使用 FTP 命令时出现 bash ftp command not found Linux中测试搭建 FTP 服务器 刚安装完 vsftpd 测试登录时就提示 bash ftp command not foun
  • 拷贝构造函数为何可以访问其他对象的私有变量?

    在学习拷贝构造函数的过程中 突然想到了非常诡异的一点 为什么新对象可以访问原对象的私有变量 如下 class Student private string name int age public Student string name in
  • Android入门(六)

    文章目录 Activity 的启动模式 standard singleTop singleTask singleInstance 技巧 了解当前界面是哪个 Activity 随时随地退出程序 启动活动的最佳写法 Activity 的启动模式
  • 语音识别——解码器(WFST、Lattice)

    解码为给定声学观测序列的前提下 找到最有可能出现的词序列 由贝叶斯得 解码的目的 从解码空间中找到一条或多条从初始状态到终止状态的最优路径 解码器是语音识别系统中的重要一环 主要解码方式有以下几种 1 动态解码器 dynamic decod
  • SpringBoot集成RabbitMQ实现消息重试机制,消息重试3次失败后写入死信队列,消息重试3次失败后入库

    yml配置 spring rabbitmq username admin password admin host localhost port 5672 virtual host publisher confirm true 发布确认 开启
  • Ubuntu小技巧17--常用软件服务配置方法2

    Ubuntu小技巧17 常用软件服务配置方法2 1 娱乐办公 2 专业工具软件 3 常见错误及注意事项 3 1 常见错误 3 2 注意事项 4 说明 笔者之前已经在博文 Ubuntu小技巧17 常用软件服务配置方法 中记录了ubuntu上大
  • UNIX网络编程卷一 学习笔记 第十章 SCTP客户/服务器程序例子

    编写一个一到多式SCTP回射客户 服务器程序 执行如下步骤 1 客户从标准输入读入一行文本 并发送给服务器 该文本行遵循 text格式 方括号中的数字表示要在这个流号上发送该文本消息 2 服务器从网络接收这个文本消息 并将接收消息的流号加1
  • pd.to_csv详解

    1 首先查询当前的工作路径 python view plain copy import os os getcwd 获取当前工作路径 2 to csv 是DataFrame类的方法 read csv 是pandas的方法 转自 https b
  • kafka java 性能测试_kafka集群部署以及java客户端测试

    本文主要讲述本人的集群部署kafka过程以及遇到的问题 其中 kafka版本为 kafka 2 10 zookeeper版本为 zookeeper 3 4 8 jdk 8u101 linux x64一 kafka以及zookeeper安装以
  • 例解基于UML的面向对象分析与设计

    http www cnblogs com leoo2sk archive 2008 11 08 1329468 html 摘要 本文以实例的方式 展示了如何使用UML进行面向对象的分析与设计 本文将假设读者对UML 面向对象等领域的基本内容
  • (一)演示如何最快的实现增删改查功能。

    1 创建及配置数据库工程 在数据库工程文件夹下添加对应的数据库工程 这里以DemonDB为例 DemonDB里的内容如下 主要包括模型实体类文件夹 T4文件夹 以及配置类 其中实体类文件夹主要用来创建表对应的实体模型类 T4则根据实体类模型
  • java并发编程的艺术

    文章目录 1 JAVA并发机制的底层实现原理 1 锁的状态 2 原子操作的实现原理 2 java内存模型 1 基础 2 重排序 4 JAVA并发编程基础 1 Synchronized底层指令 2 Thread join 5 JAVA中的锁
  • Hadoop YARN

    YARN介绍 Apache Hadoop YARN Yet Another Resource Negotiator 另一种资源协调者 是一种新的Hadoop资源管理器 YARN是一个通用资源管理系统和调度平台 可为上层应用提供统一的资源管理
  • Got minus one from a read call错误解决办法

    在我使用Oracle自带的工具sqldevloper Oracle10 11都带个工具 用起来还行 就是有点慢 登录服务器Oracle9i数据库的时候 出现了这个提示 网上一查 很多人是在执行JAVA程序的时候报了这个异常 好心人给出的明确
  • 华为社招面试笔试

    1 机试题 机试有两道题 一道题200分 120分及格 题目一 给你一个正整数n 假设有两个质数加起来等于n 问一共有多少组这样的质数 题目二 字符串匹配 给你一个父串 一个子串 求父串中子串出现的次数 温馨提示 机试题其实用暴力破解就可以
  • 使用百度地图接口实现自定义网页地图开发实现

    上午研究了下一些网站都已经实现好的地区 公交 线路等等一些基于 地图 的服务 这些服务都是基于诸如百度 谷歌地图服务接口下的二次开发 百度地图接口服务免费 而且开发文档 API介绍详细 所以本文暂先介绍如何调用百度地图服务 API http
  • java中四大作用域

    Java的四大作用域为 PageContext ServletRequest HttpSession ServletContext 下面一起了解一下Java的四大作用域吧 首先按照作用范围来算 是PageContext jsp页面
  • 路由器从外向内访问(端口转发)及从内向外访问(NAT)的配置

    路由器从外向内访问 端口转发 及从内向外访问 NAT 的配置 描述需求 最近工作上有一个需求 大致意思就是解决路由器内外访问的问题 这个问题可以分成两部分 一个是外部设备 如服务器 能主动访问路由器局域网内的主机 另一个就是内部的主机需要能
  • Java基础-反射

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