7月26日JavaSE学习笔记

反射

Java是面向对象的,有对象必须先有类, 有static修饰类的属性和方法;在Java中存储了类的内容,这个内容也应该是一个对象;Java中每一个用到的类都会加载一块内存,这每一块内存都是一个对象;这些对象记录了这些类中声明了哪些属性和方法以及构造方法,Java将这类抽象为一个Class类

类对象

类的类对象中存储了类中定义的内容:属性、方法、构造方法

Class类的对象是不能new的。

获取类对象的方式有三种:

1.通过类名获取类对象

        //通过类名获取类对象Class clazz = EasyClassA.class;

2.通过对象获取类对象

        //通过对象获取类对象clazz = new EasyClassA().getClass();

3.通过Class类的forName方法获取

        //通过Class类的forName方法获取clazz = Class.forName("com.easy725.EasyColor");

Field 类:字段

在Java中用Field类来记录类的属性

获取类中的public声明的公有属性:getField、getFields 

        c=Class.forName("com.easy726.Easy");        //获取类的属性//fName变量指向的对象就是Easy类中的name属性Field fName = c.getField("name");//传入属性名获取公共的属性

获取属性的值 get

        //可以获取某一个Easy类的对象的name属性的值Object objectName = fName.get(easy);System.out.println(objectName+"---反射");

设置属性的值 Set

        //注入该属性的值fName.set(easy,"李四");System.out.println(easy.name);

获取类中声明的任意属性:getDeclaredField

        Field fSex = c.getDeclaredField("sex");//默认访问权限Field fAddress = c.getDeclaredField("address");//私有private访问权限

访问私有属性必须先获取访问权限:setAccessible(true)

        //反射访问私有属性  必须先获取访问权限fAddress.setAccessible(true);//把访问权限设置为truefAddress.set(easy,"青岛市城阳区");System.out.println(fAddress.get(easy));

什么是反射?

在Java中,反射是指程序在运行时动态地检测、获取和操作类、对象、方法和属性的能力。通过反射,我们可以在运行时获取任意一个类的信息,包括类的名称、方法、字段等,并且可以在运行时创建对象、调用方法和访问属性。

反射就是在程序运行期间,可以动态的获取类中定义的属性和方法以及构造方法的机制(思想)的实现

反射的核心是 Class类程序中使用的每一个类,都有一个唯一的对应的Class对象


反射的API:能够调用的属性和方法 FieldMethodConstructor

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

反射会破坏类的封装性,需要通过场景说明,反射和封装没有绝对的好坏,只是应用场景不同


通过反射创建对象
Easy easy = c.newInstance();//调用类的无参构造方法创建对象

下面演示了一个通过反射创建对象的案例:利用泛型写一个方法,根据读取到的Map中的键值对,通过反射创建对象并为对应属性赋值。

    public static <T> T getInstance(Class<T> tClass, Map values) throws InstantiationException, IllegalAccessException {//通过反射获取实例  创建对象T t = tClass.newInstance();//通过类中的无参构造方法创建对象//通过反射获取类中定义的属性Field[] farr = tClass.getDeclaredFields();//获取类中声明的所有属性//System.out.println(Arrays.toString(farr));for (Field fItem:farr){//获取属性的名字String fName = fItem.getName();//获取该属性在Map中的键值对    属性对应的值Object value = values.get(fName);//设置属性访问权限fItem.setAccessible(true);fItem.set(t,value);//把t对象的fItem属性的值设置为value}return t;//返回对象t}public static void main(String[] args) throws InstantiationException, IllegalAccessException {Map map = new HashMap();map.put("code","C1001");map.put("name","张三");map.put("sex","女");Student stu = getInstance(Student.class,map);System.out.println(stu);}

Method 类:方法

在前面的Easy类中,已经写好了一个无参和一个有两个int类型参数的成员方法

    public void methodA(){System.out.println("methodA");}public void methodB(int a, int b){System.out.println("methodB");System.out.println("两个参数分别为:"+a+","+b);}

先通过类对象的 newInstance() 方法创建类的实例

        //获取类对象Class<Easy> c=Easy.class;Easy easy = c.newInstance();//创建实例

反射获取public方法:getMethod ( 传入方法名和参数列表 )

        //获取public方法,传入方法名和参数列表Method ma=c.getMethod("methodA");Method mb=c.getMethod("methodB", int.class, int.class);

面向对象的思想调用成员方法: 对象.方法名()

在反射中用 invoke ( 对象,参数 ) 驱动对象执行方法

        ma.invoke(easy);mb.invoke(easy,23,45);

Constructor 类:构造方法

前面提到,可以通过类对象的newInstance()方法直接调用无参构造方法创建实例,因而推荐每个类都要有一个无参的构造方法

        //反射获取构造方法Class<Easy> c= Easy.class;c.newInstance();//调用无参的构造方法

也可以通过 getConstructor() 方法直接获取一个构造方法的对象,因为构造函数名有约束,必须和类名相同,获取指定的构造函数只需要传入参数列表即可。

        Constructor<Easy> con = c.getConstructor();con.newInstance();//构造方法是谁就调用谁con = c.getConstructor(String.class);con.newInstance("张三");

Modifier 类:修饰符

使用Modifier的方法判断方法/属性/构造方法的修饰符

Modifier类将不同的修饰符定义为 int 类型的16进制整型常量;

相当于二进制的每一位都对应一个特定的修饰符

判断时只需要把获取的修饰符对应的整数,进行按位与运算,只要结果不为0,就说明有对应二进制位置的修饰符修饰:

        //修饰符 使用Modifier的方法判断方法/属性/构造方法的修饰符Field f = c.getDeclaredField("test");int fmod = f.getModifiers();//判断是否使用了某个修饰符Boolean bool = Modifier.isStatic(fmod);//           1 0 0 0System.out.println(fmod);//                 1 0 0 1 1 0 0 1 按位与运算不为 0System.out.println(bool);System.out.println(Modifier.toString(fmod));

内省

内省(Introspection)是一种通过反射机制来获取和操作类的属性、方法和事件的方式。

底层还是通过反射实现的,内省不会破坏封装性

通过获取属性的读方法和写方法(getter/setter)来获取和设置属性的内容,不会破坏类的封装性

        BeanInfo bi = Introspector.getBeanInfo(c);//只能获取setter和getter方法bi.getBeanDescriptor();PropertyDescriptor[] pds = bi.getPropertyDescriptors();//获取属性描述String pName = pds[0].getName();//获取属性的名字Method read = pds[0].getReadMethod();//对应属性的getter方法Method write = pds[0].getWriteMethod();//对应属性的setter方法System.out.println(pName);Easy easy = c.newInstance();write.invoke(easy,"张三");

补充

synchronized同步机制的底层原理:

synchronized在JVM内部是通过Monitor(监视器)来实现的,Monitor是一种同步机制,它依赖于底层操作系统的Mutex Lock(互斥锁)来实现。Monitor与Java对象相关联,当线程尝试进入synchronized修饰的方法或代码块时,它会尝试获取与该对象关联的Monitor的锁。

Monitor的获取与释放:当线程进入synchronized块时,它会执行一个monitorenter指令,尝试获取对象关联的Monitor的锁。如果Monitor处于无锁状态,该线程会成功获取锁,并在对象头中标记为已锁定。如果Monitor已被其他线程锁定,则进入该方法的线程将被阻塞直到获取到Monitor的锁。当线程退出synchronized块时,它会执行monitorexit指令,释放Monitor的锁,并允许其他等待的线程获取锁。


在JVM中,每个Java对象在内存中都有特定的结构,通常分为三块区域:对象头(Object Header)、实例数据(Instance Data)和对齐填充(Padding)。其中,对象头是实现synchronized同步机制的关键部分。

对象头:对象头包含了对象的元数据信息,如哈希码(Hash Code)、GC分代年龄、锁状态标志、偏向线程ID、偏向时间戳等。这部分信息在JVM中用于支持对象的同步机制。


JVM(Java Virtual Machine)生命周期

JVM的生命周期可以概括为以下几个阶段:

1. 加载(Loading)
  • 将Java字节码文件(.class文件)从磁盘加载到JVM的内存中,并创建对应的Class对象,为程序的执行准备必要的类信息。
2. 链接(Linking)
  • 验证(Verification)检查加载的字节码是否符合JVM规范,确保没有违反安全性的操作,防止执行恶意代码或包含错误的字节码。
  • 准备(Preparation)为类的静态变量分配内存空间,并赋予其Java语言规范中定义的默认值(如int为0,boolean为false等),为类的初始化做准备。
  • 解析(Resolution)将符号引用(如类名、字段名、方法名)转换为直接引用(即内存中的实际地址),确保在程序执行时能够快速地定位到类和成员。
3. 初始化(Initialization)
  • 执行类构造器<clinit>()方法中的代码,包括静态变量的显式初始化和静态代码块的内容,完成类的初始化,准备类的实例创建和方法的调用
4. 使用(Using)
  • 在JVM运行时,根据程序逻辑执行方法调用、对象创建等操作,执行Java程序的逻辑功能。
5. 卸载(Unloading)
  • 当类不再被JVM中的任何对象、线程或类加载器引用时,该类会被从内存中卸载,回收内存资源,防止内存泄漏。

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

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

相关文章

测试开发面试题---计算机网络

计算机网络模型 OSI模型&#xff1a;七层模型 物理层&#xff1a;定义电气特征&#xff0c;机械特征等功能规范&#xff0c;传递实际比特流数据链路层&#xff1a;物理地址寻址&#xff08;MAC&#xff09;&#xff0c;帧的传输&#xff0c;错误检测和纠正网络层&#xff1a;…

数据融合研究模板

摘要&#xff1a;本研究旨在深入探讨数据融合这一重要领域&#xff0c;包括其概念、方法、应用场景以及面临的挑战。通过对相关文献和实际案例的研究&#xff0c;分析数据融合在当今数字化时代的重要性和发展趋势。 一、引言 随着信息技术的飞速发展&#xff0c;数据呈现出爆…

php+bootstrap 编写简易的步骤进度条

个人笔记记录&#xff0c;步骤进度条。 版本一&#xff1a; 初始版本&#xff0c; 当前版本单纯的根据bootstrapCSS进行完成的简易版本。这个比较简单 样式我放在了最底下。 <div class"form-group steps"><div class"steps-height"><di…

如何在Linux中打开core文件

在Linux中打开core文件通常指的是使用调试工具来分析和查看core文件的内容&#xff0c;以便了解程序崩溃的原因。core文件是程序异常终止时由操作系统生成的一种内存转储文件&#xff0c;包含了程序崩溃时的内存、寄存器状态、堆栈等信息。以下是在Linux中打开core文件的一般步…

huawei 路由 RIP 协议中三种定时器的工作原理

RFC2453 定义的三种 RIP 协议定时器 更新定时器&#xff08;Update Timer&#xff09;&#xff1a;用于触发更新报文的发送&#xff0c;超时时间为 30 秒。老化定时器&#xff08;Age Timer&#xff09;&#xff1a;如果在老化时间内没有收到邻居发送的响应报文&#xff0c;则…

txt格式单词导入有道词典生词本 (java代码方式)

txt格式单词导入有道词典生词本 (java代码方式) 首先要求txt文档里单词的格式&#xff0c;大概需要像这种&#xff1a; 每行是一个单词&#xff0c;格式为&#xff1a;英文单词空格词性单词意思。 注意 导出单词本的名字就是你 txt 文件的名字 我这里是 公共英语三级 单词本 …

IAR使用调试详解

目录 1 IAR功能介绍 1.1 File文件菜单 1.2 Edit编辑菜单 1.3 View视图菜单 1.4 Projcet工程菜单 1.5Debug调试菜单 1.6 Disassembly反汇编菜单 1.7 Simulator下载调试工具 1.8 Tools工具菜单 1.9 Window窗口菜单 1.10 Help帮助菜单 2 IAR设置 2.1 插入/编辑模板 2…

如何选择最佳的云盘检测方案?

橡胶密封圈是一种用于填塞、密封或隔离物体之间空隙的圆形零件&#xff0c;通常由橡胶或类似材料制成。这些密封圈通常用于工程、机械或汽车领域&#xff0c;以防止液体、气体或其他物质泄漏。 橡胶密封圈通常对多种化学物质具有良好的耐腐蚀性能&#xff0c;使其适用于各种环…

一些关于颜色的网站

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 1、中国传统色 2、网页颜色选择器 3、渐变色网站 4、多风味色卡生成 5、波浪生成 6、半透明磨砂框 色卡组合

T-CNN——利用张量 CNN 增强缺陷检测

1. 摘要 缺陷检测是制造业中一个重要而具有挑战性的问题。本研究引入了张量卷积神经网络&#xff08;T-CNN&#xff09;&#xff0c;并在罗伯特-博世制造工厂生产的超声波传感器组件缺陷检测的实际应用中验证了其性能。与同类 CNN 模型相比&#xff0c;作者的量子启发 T-CNN 通…

【后端开发实习】Python基于Quart框架实现SSE数据传输

Python基于Quart框架实现SSE数据传输 前言SSE简介理论分析代码实现 前言 在类似Chatgpt的应用中要实现数据的流式传输&#xff0c;模仿实现打字机效果&#xff0c;SSE是不二之选。传统的Flask框架不能满足异步处理的要求&#xff0c;没有异步处理就很难实现实时交互的需求&…

Java中的object类与objects类

Java中的Object类和Objects类在Java类库中扮演着不同的角色&#xff0c;它们之间存在明显的区别。 Object类 基础与根源&#xff1a; Object类是Java类层次结构的根类。这意味着Java中的每一个类&#xff08;除了Object类本身&#xff09;都直接或间接地继承自Object类。Obje…

2024年7月解决Docker拉取镜像失败的实用方案,亲测有效

在Ubuntu 16.04、Debian 8、CentOS 7系统中&#xff0c;若遇到Docker拉取镜像失败的问题&#xff0c;以下是一些亲测有效的解决方案&#xff1a; 配置加速地址 首先&#xff0c;创建Docker配置目录&#xff1a;sudo mkdir -p /etc/docker然后&#xff0c;编辑daemon.json文件…

C++客户端Qt开发——Qt窗口(对话框)

5.对话框 ①对话框介绍 对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者简洁的用户交互。Qt常用的内置对话框有&#xff1a;QFiledialog…

【第四天】计算机网络知识 HTTP1.0,HTTP1.1与HTTP2.0的区别 HTTP3.0

HTTP1.0&#xff0c;HTTP1.1与HTTP2.0的区别 HTTP1.0 默认是短链接&#xff0c;可以强制开启长连接。HTTP1.1默认长连接。HTTP2.0采用多路复用。 HTTP1.0&#xff1a; 默认使用短链接&#xff0c;每次请求都需要建立一个TCP连接。它可以设置&#xff1a;Connection: keep-aliv…

利用OSMnx求路网最短路径并可视化(二)

书接上回&#xff0c;为了增加多路径的可视化效果和坐标匹配最近点来实现最短路可视化&#xff0c;我们使用图形化工具matplotlib结合OSMnx的绘图功能来展示整个路网图&#xff0c;并特别高亮显示计算出的最短路径。 多起终点最短路路径并计算距离和时间 完整代码#运行环境 P…

洛谷 P9854 [CCC 2008 J1] Body Mass Index

这题让我们计算出 BMI 值&#xff0c;随后判断属于哪个等级。 BMI 值计算公式&#xff1a; ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​。 BMI 范围 对应信息 …

【JVM基础08】——类加载器-说一下类加载的执行过程?

目录 1- 引言&#xff1a;类加载的执行过程1-1 类加载的执行过程是什么&#xff1f;(What) 2- ⭐核心&#xff1a;详解类加载的执行过程(How)2-1 加载——>加载到运行时数据区2-2 验证——>类的安全性检查2-3 准备——>为类变量分配内存并设置初始值2-4 解析——>把…

Web网页端IM产品RainbowChat-Web的v7.1版已发布

一、关于RainbowChat-Web RainbowChat-Web是一套Web网页端IM系统&#xff0c;是RainbowChat的姊妹系统&#xff08;RainbowChat是一套基于开源IM聊天框架 MobileIMSDK (Github地址) 的产品级移动端IM系统&#xff09;。 ► 详细介绍&#xff1a;http://www.52im.net/thread-2…

每天一个设计模式之职责链模式(第一天)

特别感谢刘伟老师&#xff0c;看他的书我学到了很多东西&#xff0c;从今天开始我要开始更新啦&#xff01; 在csdn个人博客来总结知识&#xff0c;把他们变成自己的能力。 对三&#xff0c;要不起&#xff0c;张三李四王五几个人在玩斗地主&#xff0c;过过过&#xff0c;一…