java进阶—重要概念反射

news2024/11/17 2:38:55

反射概念

反射: 它是java中的一个很重要的概念,是框架设计的灵魂

框架呢?就是一个半成品软件,我们在这半成品上进行开发,比如我们经常提到spring springmvc springboot spingcloud 等等

也许有的小伙伴会说,框架别人都写好了,我只要在上进行CURD就行了,还要学习反射干什么?,话是这么说,但知道反射,对于后续框架的学习与应用会更加得心应手

反射是在运行状态中,将一个类的每一个组成部分(属性,构造,方法等等) 进行封装,任何一个对象都能进行调用这个类的 属性,构造,方法,这个过程就是反射机制

有点迷?看不懂,没关系

我们先来看一下,你写的java类在虚拟机中是怎么样运行的,它经历了什么

在这里插入图片描述
图解析 :

第一阶段:

一个 .java文件在编译期,它会被 javac命令 编译成 .class字节码文件

第二阶段:

编译好的.class文件会被类加载器导入到内存中,形成Class类对象,一个类对象会有成员变量,成员方法,构造方法 等等,这些都可能会有多个,于是就把它封装成用数组来归类存储

第三阶段:

就是运行时阶段了,就是我们常用的new一个对象,来使用

我们new一个对象,底层就是通过Class类阶段创建出来的

回过头来看反射机制那段话,现在是不是对反射机制有更好的理解了呢

反射有哪些好处呢?我们为什么要用反射

首先,反射可以在运行过程中,操作这些对象 ,不理解,没关系,举个例子

给大家看张图

在这里插入图片描述
搞错了

在这里插入图片描述
不知道大家是不是在使用idea进行编程的,idea这个编译器其实就用到了反射

在这里插入图片描述
看到这些方法了没,其实用的就是反射机制,这些方法封装到method数组中,我们idea就是一个程序,它是不是一直在运行,就把list的方法,展示到这个列表中 ,在运行中,我们就知道这个集合中有哪些方法

其次,就是反射可以提高程序可扩展性

反射API

获取Class方式:

先创建一个person类


package com.test1.demo;

public class Person {

    private String name;
    private Integer age;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

1. Class.forName(“全类名”) :将字节码加载进内存,返回Class文件

 //获取class
        try {
            Class<?> clazz = Class.forName("com.test1.demo.Person");
            System.out.println(clazz);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述
2. 类名.class : 通过类名属性获取


        //获取class
        Class<Person> clazz = Person.class;
        System.out.println(clazz);

在这里插入图片描述
3. 对象.getClass

   //获取class
        Person person = new Person();
        System.out.println(person.getClass());

注意:同一个字节码文件(.class) 文件,只会被加载一次,不论哪一种方式获取的class对象都是同一个对象

 @Test
    public void tes9() throws ClassNotFoundException {
        //获取class

        Class<?> clazz = Class.forName("com.test1.demo.Person");
        System.out.println(clazz);

        Class<Person> clazz1 = Person.class;
        System.out.println(clazz1);

        Person person = new Person();
        Class<? extends Person> clazz2 = person.getClass();
        System.out.println(clazz2);

        //判断是不是同一个对象  == 

        System.out.println(clazz == clazz1);
        System.out.println(clazz == clazz2);
    }

这三种方式,该选择哪一种呢?

分情况

Class.forName(“全类名”) 这种方式多用于配置文件,读取文件,加载类

类名.class 多用于参数传递

对象.getClass 一般情况下,有对象了,去获取字节码的方式

常用Class的方法:

1. 获取成员变量组合

getFields() 和 getDeclaredFields()

注意:这两个是有区别的, getFields() 是只能获取这个类中公共的字段,也就是只能获取修饰符是 public 的变量,并且包括父类中的字段

getDeclaredFields() 能获得某个类声明的所有变量,但不包括父类

很简单!!来个例子

现在有一个 Person 类,一个Animal 类,Person 类继承于 Animal

注意看 两个类中成员变量的 修饰符


public class Person  extends Animal{

    private String  personName;

    public  Integer personAge;

}



public class Animal{

    private Integer animalName;
    public String animalAge;

}

测试1:

//获取class
         Class<Person> clazz1 = Person.class;
         Field[] fields = clazz1.getFields();
        for (Field field : fields) {
            System.out.println(field.getType()+"...." +field.getName());
        }

输出结果:
在这里插入图片描述
可以看出,getFields() 只能获取public 修饰的变量,并且能获取父类中的public修饰变量

测试2:

//获取class
        Class<Person> clazz1 = Person.class;
        Field[] fields = clazz1.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getType() + "...." + field.getName());
        }

输出结果:

在这里插入图片描述
可以看出getDeclaredFields() 可以获取 所有声明成员变量,但无法获取父类

2. 获取构造方法

创建一个Perosn 类 ,有两个属性,分别赋予 全参构造,单参构造和 无参构造

public class Person  {

    private String  name;

    public  Integer age;


    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    private Person(String name) {
        this.name = name;
    }
}

  • getDeclaredConstructors() 获取所有构造函数
   //获取class
        Class<Person> clazz1 = Person.class;
        Constructor<?>[] declaredConstructors = clazz1.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

在这里插入图片描述

  • getConstructors() 获取所有public 构造函数

 //获取class
        Class<Person> clazz1 = Person.class;
        Constructor<?>[] declaredConstructors = clazz1.getConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

在这里插入图片描述

  • getConstructor() 获取无参构造函数
   //获取class
        Class<Person> clazz1 = Person.class;
        Constructor<Person> constructor = clazz1.getConstructor();
        System.out.println(constructor);

在这里插入图片描述
这边把无参构造换成私有的,还能不能获取呢?

答案是:不能 ,有兴趣的小伙伴可以试试,会报错,贴出来给大家看看

在这里插入图片描述

  • getDeclaredConstructor(Class<?>… parameterTypes) 根据参数类型获取构造

 //获取class
        Class<Person> clazz1 = Person.class;
        Constructor<Person> declaredConstructor = clazz1.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);

在这里插入图片描述
以上便是反射的基本使用了!!

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

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

相关文章

Tdengine 时序数据库-安装与客户端连接

使用 TDengine 时序数据库的版本是 2.4.0.0 使用的安装RPM的安装方便安装 TDengine-server-2.4.0.0-Linux-x64.rpm 1. 安装指令: rpm -ivh TDengine-server-2.4.0.0-Linux-x64.rpm [rootnode3 server]# rpm -ivh TDengine-server-2.4.0.0-Linux-x64.rpm Verifying... …

python的格式化输出

print中的占位符(%-fomatting) print中的%d,%s等&#xff0c;只是一个占位符&#xff0c;等正确内容到了再查进去。 注意&#xff1a;变量值和打印内容之间不能有逗号隔开。 使用fomat方法 format底层可以理解成一个字典&#xff0c;默认key是按顺序从0开始&#xff0c;指定key…

nginxWebUI runCmd RCE漏洞复现

0x01 产品简介 nginxWebUI是一款图形化管理nginx配置的工具&#xff0c;能通过网页快速配置nginx的各种功能&#xff0c;包括HTTP和TCP协议转发、反向代理、负载均衡、静态HTML服务器以及SSL证书的自动申请、续签和配置&#xff0c;配置完成后可以一键生成nginx.conf文件&#…

网络变压器卷盘(封装载带)封膜压力标准

Hqst华强盛导读&#xff1a;网络变压器封装载带封膜压力标准通常是根据具体产品的封装材料和尺寸来确定的。 网络变压器封装载带封膜压力标准通常是根据具体产品的封装材料和尺寸来确定的。一般来说&#xff0c;封装载带的封膜压力应该足够大&#xff0c;以确保封装过程中封膜…

安卓开发基于KeyStore对数据进行加解密

问题背景 在我们App开发过程中&#xff0c;可能会涉及到一些敏感和安全数据需要加密的情况&#xff0c;比如登录token的存储。我们往往会使用一些加密算法将这些敏感数据加密之后再保存起来&#xff0c;需要取出来的时候再进行解密。 此时就会有一个问题&#xff1a;用于加解密…

计算机网络—应用层

文章目录 网络应用基本原理网络应用体系结构~三种结构网络应用进程通信网络应用需求 WEB应用HTTP协议Cookie技术WEB缓存/代理服务器技术 Email应用SMTP协议Email消息格式&#xff08;SMTP传输消息的格式&#xff09;POP3协议IMAP DNS应用DNS协议 网络应用基本原理 网络应用体系…

adb 工具

小白初如嵌入式的坑&#xff0c;对于串口调试工具&#xff0c;之前一直只知道有SecureCRT这一种方式&#xff1b; 但是在最近一次的使用过程中&#xff0c;发现抢占资源的情况出现&#xff0c;两个进程之间相互打架&#xff0c;这个时候需要 查看top&#xff08;嵌入式板子资…

Kernel panic – not syncing: Attempted to kill init! Redhat6.2故障修复

1、Linux环境 Redhat6.2&#xff0c; Linux version 2.6.32-220.el6.i686 (mockbuildx86-003.build.bos.redhat.com) (gccversion 4,4.5 20110214 (Red Hat 4.4.5-6) (GCC) ) #1 SMP Wed Nov 9 08:02:18 EST 2011 2、故障现象 修改TCP相关文件&#xff0c;重启完Linux系统之…

银河麒麟V10搭建达梦8数据库

大家好&#xff0c;我是早九晚十二&#xff0c;目前是做运维相关的工作。写博客是为了积累&#xff0c;希望大家一起进步&#xff01; 我的主页&#xff1a;早九晚十二 目前&#xff0c;国产化服务器越来越多&#xff0c;操作系统的国产化使得大家对中间件都有了需求&#xff0…

alpha值大小对lasso回归结果的影响

LASSO 回归 的特点是在拟合广义线性模型的同时进行变量筛选&#xff08;variable selection&#xff09;和复杂度调整&#xff08;regularization&#xff09;。因此不论目标因变量&#xff08;dependent/response varaible&#xff09;是连续的&#xff08;continuous&#xf…

【FFmpeg实战】视频基础和MP4容器解封装

转载自原文地址&#xff1a;https://juejin.cn/post/6901218687081480206 一、视频的编解码方式 谈到视频&#xff0c;我们经常会听到视频编解码、H.264等诸如此类的内容。那么视频编解码是什么意思呢&#xff1f; 视频编解码&#xff0c;其实就是对视频数据进行压缩和解压缩…

ros版本KF-GINS(带有rviz可视化结果显示及文件生成)

原始的KF-GINS是基于读写文件实现的&#xff0c;在此基础上改进了ros版本&#xff0c;将原始数据文件转换为rosbag格式&#xff0c;并实现了rviz下的可视化结果显示&#xff0c;代码已共享至github https://github.com/slender1031/kf-gins-ros 感谢武汉大学卫星导航定位技术研…

IT培训的背后,是“韭菜”的躺赚梦!

本文只谈"骗局"&#xff0c;不谈其他&#xff0c;绝不引战&#xff0c;如有错误&#xff0c;希望指出我会及时改正。 实际也有大量做得好的、值得肯定的培训机构&#xff0c;这里需要大家仔细鉴别。 导语 为什么要写这篇文章呢&#xff0c;近些年培训这个话题也比较…

Mhz_c1f靶场-简记

靶机 名称&#xff1a;mhz_cxf:clf download url&#xff1a;https://www.vulnhub.com/entry/mhz_cxf-c1f,471/ IP地址探测 sudo netdiscover -i eth1 -r 192.168.56.0/24 sudo netdiscover -i eth1 -r 192.168.56.0/24 Currently scanning: 192.168.56.0/24 | Screen …

ARM Trace32(劳特巴赫) 使用介绍 1 - Veloce 环境中使用 Trace32 介绍

文章目录 背景1.1 Trace 启动1.1.1 Trace32 系统相关设置 1.2 Trace 常用命令1.2.2 加在bin文件1.2.3 寄存器常用命令1.2.4 内存(寄存器)数据修改 1.3 变量相关命令 背景 Veloce是一款基于FPGA的高速仿真器&#xff0c;可用于验证芯片设计和软件开发, 它和 Trace32 都可以用于…

16.RocketMQ之消费重试以及原理

highlight: arduino-light 1.4 消费重试 对于顺序消息,当消费者消费消息失败后,消费者会在本地自动不断进行消息重试,每次间隔时间为 1 秒,重试最大值是 Integer.MAX_VALUE。 对于无序消息(普通、定时、延时、事务消息)当消费者消费消息失败时可以通过设置返回状态达到重试的目…

湿地环境监测物联网解决方案

湿地作为生态系统的关键组成部分&#xff0c;发挥着涵养水源、调节气候、改善环境、维护生物多样性等生态功能。湿地提供了独特的生境&#xff0c;为许多鸟类、鱼类和其他野生动物提供了栖息地和食物来源。此外&#xff0c;湿地还具有保持水量平衡和水质净化的重要功能&#xf…

最优控制:代数黎卡提方程ARE(Algebraic Riccati Equation)

本文介绍代数黎卡提方程的Matlab解法&#xff0c;包括直接求解和迭代求解 问题描述&#xff1a; 一、数值解法 可以看出&#xff0c;ARE方程是关于P的一个非线性方程&#xff0c;当系统矩阵维度较高时&#xff0c;难以求解&#xff0c;但是MATLAB给出了求解ARE的函数care % 系…

颜色聚合向量 Color Co-ccurrence Vector 介绍以及MATLAB代码实现

这件事情的起因是我想复习一下我在亚太杯数学建模当中使用过的CCV这种方法&#xff0c;但是CSDN平台上找了半天都没有&#xff0c;所以后来决定Google一下&#xff0c;终于找到了&#xff0c;甚至还有实现的代码&#xff0c;因此放上来。原文见Dr. Mahmoud Attia的博客。 一、…

JAVA中的伪共享与缓存行

一.伪共享与缓存行 1.CPU缓存架构 CPU 是计算机的心脏&#xff0c;所有运算和程序最终都要由它来执行。 主内存&#xff08;RAM&#xff09;是数据存放的地方&#xff0c;CPU 和主内存之间有好几级缓存&#xff0c;因为即使直接访问主内存也是非常慢的。 CPU的速度要远远大…