反射(Reflection) --Java学习笔记

news2024/11/27 16:25:58

反射

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

反射学什么?

学习获取类的信息、操作它们

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

全部认识完后,再看反射的应用场景

1、反射第一步:加载类,获取类的字节码:Class对象

获取Class对象的三种方式

  • Class c1=类名.class
  • 调用Class提供方法:  public static Class forName(String package)
  • Object提供的方法:  publicClass getClass();  Class c3=对象.getClass()

代码演示:

package com.zeyu.reflect;

public class Test1Class {
    public static void main(String[] args) throws Exception {
        Class c1 = Student.class;
        System.out.println(c1.getName());   //全类名
        System.out.println(c1.getSimpleName()); //简名:Student

        Class c2 = Class.forName("com.zeyu.reflect.Student");   //填全类名
        System.out.println(c1 == c2);   //拿到的是同一个对象

        Student s = new Student();  //创建类的实例
        Class c3 = s.getClass();    //调用getClass方法
        System.out.println(c3 == c2);   //拿到的依旧是同一个对象
    }
}

运行结果:

2、获取类的构造器:Constructor对象

Class提供了从类中获取构造器的方法

获取类构造器的作用:依然是初始化对象返回

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class Test2Constructor {
    @Test
    public void testGetConstructors() {
        //1、反射第一步,必须先得到这个类的class对象
        Class c = Cat.class;
        //2、获取类的全部构造器
//        Constructor[] constructors = c.getConstructors();   //只能拿public类型的构造器
        Constructor[] constructors = c.getDeclaredConstructors();
        //3、遍历数组中的每一个构造器对象
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());
        }
    }

        @Test
        public void testGetConstructor() throws Exception {
            //1、反射第一步,必须先得到这个类的class对象
            Class c = Cat.class;
            //2、获取某一个构造器:无参构造器
//            Constructor constructor = c.getConstructor(); //只能拿public类型的构造器
            Constructor constructor = c.getDeclaredConstructor();   //存在就能拿到
            System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());
            constructor.setAccessible(true);    //禁止检查访问权限
            Cat cat = (Cat) constructor.newInstance();  //调用构造器完成对象初始化
            System.out.println(cat);

            //获取有参构造器
            Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
            System.out.println(constructor2.getName() + "-->" + constructor2.getParameterCount());
            constructor2.setAccessible(true);
            Object cat2 = constructor2.newInstance("黑猫警长", 3);  //初始化对象
            System.out.println(cat2);
        }
}

运行结果:

也可以用反射破坏单例设计模式

3、获取类的成员变量:Field对象

Class提供了从类中获取成员变量的方法

获取到成员变量的作用:依然是赋值、取值

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Field;

public class Test3Field {
    @Test
    public void testGetFields() throws Exception {
        //反射第一步,必须先拿到类的class对象
        Class c = Cat.class;
        //获取类的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历这个成员变量数组
        for (Field field : fields) {
            System.out.println(field.getName() + "--->" + field.getType());
        }

        //拿到某个成员变量
        Field fName = c.getDeclaredField("name");
        System.out.println(fName.getName() + "--->" + fName.getType());

        Field fAge = c.getDeclaredField("age");
        System.out.println(fAge.getName() + "--->" + fAge.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);
    }
}

运行结果:

4、获取类的成员方法:Method对象

Class提供了从类中获取成员方法的API

成员方法的作用:依然是执行

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Method;

public class Test4Methods {
    @Test
    public void TestGetMethods() throws Exception {
        //1、反射第一步,先得到类的class对象
        Class c = Cat.class;
        //2、获取类的全部成员方法
        Method[] methods = c.getDeclaredMethods();
        //3、遍历这个数组的每个方法对象
        for (Method method : methods) {               //getParameterCount()统计形参个数
            System.out.println(method.getName() + "--->" + method.getParameterCount() + "--->"
            + method.getReturnType());
        }
        //4、获取某个方法对象
        Method run = c.getDeclaredMethod("run");
        System.out.println(run.getName() + "--->" + run.getParameterCount() + "--->"
                + run.getReturnType());

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

        Cat cat = new Cat();
        run.setAccessible(true);    //禁止检查访问权限
        Object rs = run.invoke(cat);//调用无参run方法,用cat对象调用
        System.out.println(rs); //无返回值,返回结果为空

        eat.setAccessible(true);
        Object rs2 = (String) eat.invoke(cat, "鱼");
        System.out.println(rs2);
    }
}

运行结果:

反射的作用?

  • 基本作用:可以得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 最重要的用途是:适合做lava的框架,基本上,丰流的框架都会基于反射设计出一些通用的功能

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

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

实现步骤

  1. 定义一个方法,可以接收任意对象
  2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
  3. 遍历成员变量,然后提取成员变量在该对象中的具体值
  4. 把成员变量名、和其值,写出到文件中去即可

代码演示:

实现类:

package com.zeyu.reflect;

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

public class ObjectFrame {
    //保存任意对象的字段和数据到文件中去
    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("src\\com\\zeyu\\reflect\\data.txt",true));
        //obj是任意对象,到底有多少字段需要保存
        Class c = obj.getClass();
        String cname = c.getSimpleName();
        ps.println("------------------" + cname + "------------------");
        //从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历每个成员变量
        for (Field field : fields) {
            field.setAccessible(true);
            //拿到成员变量的名字
            String name = field.getName();
            //拿到这个成员变量在对象中的数据
            String value = field.get(obj) + "";
            ps.println(name + "=" + value);
        }
        ps.close();
    }
}

测试类:

package com.zeyu.reflect;

import org.junit.Test;

public class Teat5ObjectFrame {
    @Test
    public void testSave() throws Exception {
        Cat cat = new Cat("小橘",2);
        Student s = new Student("小明","男",22,172.8);

        ObjectFrame.saveObject(cat);
        ObjectFrame.saveObject(s);
    }
}

运行结果:

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

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

相关文章

利用vivid包,点亮机器学习模型图:惊艳的可视化新体验

一、引言 随着大数据时代的到来,机器学习技术在各个领域得到了广泛的应用。然而,由于机器学习模型的复杂性和抽象性,理解和解释这些模型往往是一项挑战。因此,机器学习可视化成为了连接数据和模型理解之间的桥梁,具有至…

DP:子数组模型

一、最大子数组和 . - 力扣&#xff08;LeetCode&#xff09; 二、环形子数组的最大和 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int maxSubarraySumCircular(vector<int>& nums) {//动态规划思想解决 //环形数组问题&#xff0c;尝试转…

AIGC实战——StyleGAN(Style-Based Generative Adversarial Network)

AIGC实战——StyleGAN 0. 前言1. StyleGAN1.1 映射网络1.2 合成网络1.3 自适应实例归一化层1.4 风格混合1.5 随机变化 2. StyleGAN 生成样本3. StyleGAN23.1 权重调制与解调3.2 路径长度正则化3.3 非渐进式增长 4. StyleGAN2 生成样本小结系列链接 0. 前言 StyleGAN (Style-Ba…

STM32F4 IAP跳转APP问题及STM32基于Ymodem协议IAP升级笔记

STM32F4 IAP 跳转 APP问题 ST官网IAP例程Chapter1 STM32F4 IAP 跳转 APP问题1. 概念2. 程序2.1 Bootloader 程序 问题现象2.2. APP程序 3. 代码4. 其他问题 Chapter2 STM32-IAP基本原理及应用 | ICP、IAP程序下载流程 | 程序执行流程 | 配置IAP到STM32F4xxxChapter3 STM32基于Y…

linux-docker安装nginx

1.拉取镜像&#xff1a; docker pull nginx2.创建挂在路径&#xff1a; mkdir -p /usr/local/nginx/conf mkdir -p /usr/local/nginx/logs mkdir -p /usr/local/nginx/www mkdir -p /usr/local/nginx/conf.d 3.启动镜像:为了拿到位置文件&#xff0c;先启动下 docker run -…

本地项目提交 Github

工具 GitIdeaGithub 账号 步骤 使用注册好的 Github 账号&#xff0c;登陆 Github&#xff1b; 创建 Repositories (存储库)&#xff0c;注意填写图上的红框标注&#xff1b; 创建完成之后&#xff0c;找到存储库的 ssh 地址或 https 地址&#xff0c;这取决于你自己的配置…

linux网络知识

七层模型 应用层 为操作系统或者网络应用程序提供网络服务的接口 表示层 解决不同系统之间的通信问题&#xff0c;负责数据格式的转换 会话层 自动收发包&#xff0c;自动寻址&#xff0c;负责建立和断开连接 传输层 将上层数据分段并提供端到端的…

Qt/C++推流组件使用说明

2.1 网络推流 公众号&#xff1a;Qt实战&#xff0c;各种开源作品、经验整理、项目实战技巧&#xff0c;专注Qt/C软件开发&#xff0c;视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发。 公众号&#xff1a;Qt入门和进阶&#xff0c;专门介绍Qt/C相关知识点学…

17. 【Android教程】开关控件ToggleButton/Switch

本节要学的两个控件是我们在使用 Android 手机时经常会用到的&#xff0c;相信大家对它并不陌生&#xff0c;甚至是非常熟悉&#xff0c;但是现实是很多开发者并不了解开关控件&#xff0c;所以会花不少功夫通过 TextView 或 Button 来实现开关功能&#xff0c;殊不知 Android …

CSS 实现无限波浪边框卡片

CSS 实现无限波浪边框卡片 效果展示 鼠标悬停效果&#xff0c;底部色块的边框是无限滚动的波浪 鼠标没有悬停效果 CSS 知识点 CSS 基础知识回顾使用 radial-gradient 实现波浪边框使用 anumate 属性实现波浪边框动画和控制动画运动 波浪实现原理 波浪边框的实现思路其…

【产品】ADW300 无线计量仪表 用于计量低压网络的三相有功电能

1 概述 ADW300 无线计量仪表主要用于计量低压网络的三相有功电能&#xff0c;具有体积小、精度高、功能丰富等优点&#xff0c;并且可选通讯方式多&#xff0c;可支持 RS485 通讯和 Lora、2G、NB、4G 等无线通讯方式&#xff0c;增加了外置互感器的电流采样模式&#xff0c;从…

day6 nest商业项目初探·二(java转ts全栈/3R教室)

背景&#xff1a;今天看3r教室开放的这个项目 【美国 | 3.6w】TS全栈&#xff1a;Goflashdeals代购返利网站 &#xff08;2022.09&#xff09; - 3R酷 | 爱自由,不打工&#xff01;一个属于3R会员的社区 (3rku.com)省流&#xff1a;web程序起来了&#xff0c;admin没起来&#…

CUDA 12.4文档2 内核线程架构

本博客参考官方文档进行介绍&#xff0c;全网仅此一家进行中文翻译&#xff0c;走过路过不要错过。 官方网址&#xff1a;https://docs.nvidia.com/cuda/cuda-c-programming-guide/ 本文档分成多个博客进行介绍&#xff0c;在本人专栏中含有所有内容&#xff1a; https://bl…

分享|如何知道自己是不是大数据信用黑名单?

随着大数据技术在金融贷前审核环节中的运用&#xff0c;早在多年前都形成了大数据信用&#xff0c;大数据信用作为辅助的风控工具&#xff0c;作用变得十分重要&#xff0c;其中大数据黑名单就是大数据差的重要一种&#xff0c;那如何知道自己是不是大数据信用黑名单呢?本文详…

Linux:gcc

Linux&#xff1a;gcc gcc概述语言发展史gcc的编译过程预处理编译汇编 gcc的链接过程动态库与静态库 gcc概述 GCC&#xff08;英文全拼&#xff1a;GNU Compiler Collection&#xff09;是 GNU 工具链的主要组成部分&#xff0c;是一套以 GPL 和 LGPL 许可证发布的程序语言编译…

python--正则表达式,元字符,反义符,转义符,位数问题

正则表达式&#xff08;regular expression&#xff09;&#xff1a; 为什么使用正则表达式&#xff1a; 在软件开发过程中&#xff0c;经常会涉及到大量的关键字等各种字符串的操作&#xff0c;使用正则表达式能很大程度的简化开发的复杂度和开发的效率&#xff0c;所以pytho…

麒麟V10安装Redis6.2.6

1、下载redis安装包 Redis各版本下载&#xff1a;https://download.redis.io/releases/ 2、将下载后的.tar.gz压缩包上传到到服务器自定义文件夹下 3、 解压文件 tar -zxvf redis-6.2.6.tar.gzmv redis-6.2.6 redis4、安装redis 在redis文件夹下输入make指令 cd /opt/redi…

【React】react 初学增删改查购物车案例

界面 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>react-购物车案例</title><…

华为OD机试 - 机器人搬砖 - 二分查找(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

centos 7.9 nginx本地化安装,把镜像改成阿里云

1.把centos7.9系统切换到阿里云的镜像源 1.1.先备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup1.2.下载新的CentOS-Base.repo配置文件 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo特别…