百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

大厂难进清华学霸整理的Java反射机制笔记,让你面试一面即中

toyiye 2024-06-21 12:04 9 浏览 0 评论

今日分享开始啦,请大家多多指教~

1.一个需求引出反射

需求如下:

根据配置文件re.properties中的指定信息,创建Cat对象并调用方法hi

配置文件中代码:classfullpath=com.hspedu.Cat,method=hi

这样的需求在学习框架时非常多,通过外部文件配置,在不修改源码情况下控制程序

符合设计模式的ocp原则(开闭原则:不修改源码,扩容功能)

代码如下:

1.使用Properties类读写配置文件

2.使用传统方式创建对象行不通,需要使用 反射机制

  • 加载类,返回Class类型的对象
  • 通过 cls对象 得到加载的类 com.hspedu.Cat 的对象
  • 通过 cls对象 得到加载的类 com.hspedu.Cat 的 methodName 方法对象,在反射机制中,可以把方法视为对象(万物皆对象)
  • 通过 method1 调用方法:即通过方法对象实现调用方法

此时我们发现,我们只需要将re.properties中的 method=hi 改成 method=cry,就会调用cry(),不需要修改源码,反射机制非常强大!

2、反射机制

2.1 Java Reflection

反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(比如:成员变量,构造器,成员方法等),并能操作对象的属性及方法。反射在设计模式和框架的底层都会用到。

加载完类之后,在堆内存中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以形象称之为:反射。

2.2 反射机制原理图

2.3 反射机制可以完成的功能

  • 在运行时,判断任意一个对象所属的类
  • 在运行时,创建任意一个类的对象
  • 在运行时,得到任意一个类所具有的成员变量和方法
  • 在运行时,调用任意一个对象的成员变量和方法
  • 生成动态代理

2.4 反射相关的主要类

这些类在 java.lang.reflection包下:

  • java.lang.Class:代表一个类,Class对象表示某个类加载后在堆内存中的对象
  • java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法
  • java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
  • java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器

代码展示如下:

2.5 反射优点和缺点

优点:可以动态地创建和使用对象(就是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。

缺点:使用反射基本是解释执行,对执行速度有影响

2.6 反射调用优化——关闭访问检查

  • Method、Field、Constructor对象都有setAccessible()方法
  • setAccessible()作用是启动和禁用访问安全检查开关
  • 参数为true表示:反射的对象在使用时取消访问检查,提高反射的效率。
  • 参数为false表示:反射的对象执行访问检查

代码展示如下:

3、Class类

3.1 基本介绍

  • Class也是类,因此也继承Object类
  • Class类对象不是new出来的,而是系统创建的
  • 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  • 每个类的实例都会记得自己是由哪个Class实例生成
  • 通过Class对象可以完整地得到一个类的完整结构,通过一系列API
  • Class对象存放在堆内存中
  • 类的字节码二进制数据存放在方法区中,有的地方称为类的元数据(包括:方法,变量名,方法名,访问权限等)

3.2 Class类的常用方法

代码展示如下:

4.获取Class类对象

5.哪些类型有Class对象

  • 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
  • 接口
  • 数组
  • 枚举
  • 注解
  • 基本数据类型
  • void

代码展示如下:

6.类加载

6.1 基本说明

反射机制是Java实现动态语言的关键,也就是通过反射实现类的动态加载。

  • 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
  • 动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,也不报错,降低了依赖性

6.2 类加载时机

  • 当创建对象时(new)——静态加载
  • 当子类被加载时,父类也加载——静态加载
  • 调用类中的静态成员时——静态加载
  • 通过反射——动态加载

6.3 类加载过程图

6.4 类加载三个阶段完成任务

6.4.1 加载阶段

6.4.2 连接阶段——验证

1.目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证、字节码验证和符号引用验证[举例说明]

3.可以考虑使用-Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。

6.4.3 连接阶段——准备

1. JVM 会在该阶段对静态变量, 分配内存并默认初始化(对应数据类型的默认初始值,如0、OL、null. false 等)。这些变量所使用的内存都将在方法区中进行分配。

2.举例说明: ClassLoad02.java

6.4.4 连接阶段——解析

虚拟机将常量池内的符号引用替换为直接引用的过程。

6.4.5 Initialization(初始化)

1.到初始化阶段,才真正开始执行类中定义的Java程序代码,此阶段是执行。

< clinit>()方法的过程。

2. <clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,井进行合井。[举例说明ClassLoad03.java]

3.虚拟机会保证一个类的 <clinit> ()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类, 那么只会有一一个线程去执行这个类的<clinit> 0方法,其他线程都需要阻塞等待,直到活动线程执行<clinit> 0方法完毕[debug源码]

代码展示如下:

1.加载B类,并生成对应的Class类对象

2.连接 num = 0;

3.初始化阶段:依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并合并。

7、通过反射获取类的结构信息

7.1 java.lang.Class类

com.hspedu.reflection ReflectionUtilsjava

1. getName:获取全类名

2. getSimpleName:获取简单类名

3. getFields:获取所有public修饰的属性,包含本类以及父类的

4. getDeclaredFields:获取本类中所有属性

5. getMethods:获取所有public修饰的方法,包含本类以及父类的

6. getDeclaredMethods:获取本类中所有方法

7. getConstructors:获取本类所有public修饰的构造器

8. getDeclaredConstructors:获取本类中所有构造器

9. getPackage:以Package形式返回包信息

10.getSuperClass:以Class形式返回父类信息

1.getinterfacs:以Class[]形式返回接口信息

12.getAnnotations:以Annotation[]形式返回注解信息

7.2 java.lang.reflect.Field类

1. getModifiers:以int形式返回修饰符

[说明:默认修饰符是0,public 是1,private 是2,protected 是4 ,static是8,final 是16] , public(1) + static (8) = 9

2. getType:以Class形式返回类型

3. getName:返回属性名

7.3 java.lang.reflect.Method类

1. getModifiers:以int形式返回修饰符

[说明:默认修饰符是0,public 是1,private是2,protected是4,static是8,final 是16]

2. getReturnType:以Class形式获取返回类型

3. getName:返回方法名

4. getParameterTypes:以Class[]返回参数类型数组

7.4 java.lang.reflect.Constructor类

1. getModifiers:以int形式返回修饰符

2. getName:返回构造器名 (全类名)

3. getParameterTypes:以Class[返回参数类型数组

代码展示如下:

8、通过反射创建对象

1.方式一: 调用类中的public修饰的无参构造器

2.方式二:调用类中的指定构造器

3. Class类相关方法

  • newlnstance :调用类中的无参构造器,获取对应类的对象
  • getConstructcor(Class..clazz):根据参数列表,获取对应的public构造器对象
  • getDecalaredConstructor(Class..clazz):根据参数列表,获取对应的所有构造器对象

4. Constructor类相关方法

  • setAccessible:暴破
  • newlnstance(object...obj):调用构造器

测试 1:通过反射创建某类的对象,要求该类中必须有 public 的无参构造

测试 2:通过调用某个特定构造器的方式,实现创建某类的对象

1. 先获取到User类的Class对象

2. 通过public的无参构造器创建实例

3. 通过public的有参构造器创建实例

  • 先得到对应构造器
  • 创建实例,并传入实参

4. 通过非public的有参构造器创建实例

  • 得到private的构造器对象
  • 创建实例

9、通过反射访问类中的成员

9.1 访问属性

1.根据属性名获取Field对象

Field f = clazz对象.getDeclaredField(属性名);

2.暴破: f.setAccessible(true); //f是Field

3.访问

  • f.set(o,值); //o表示对象
  • syso(f.get))://o表示对象

4.注意:如果是静态属性,则set和get中的参数o,可以写成null

代码展示如下:

1. 得到Student类对应的 Class对象

2. 创建对象

3. 使用反射得到age 属性对象

4. 使用反射操作name 属性

9.2 访问方法

1.根据方法名和参数列表获取Method方法对象: Method m =

clazz.getDeclaredMethod(方法名,XX.class); //得到本类的所有方法

2.获取对象: Object o= clazz.newInstance();

3.暴破: m.setAccessible(true);

4.访问: Object returnValue = m.invoke(o,实参列表);//o就是对象

5.注意:如果是静态方法,则invoke的参数o,可以写成null!

代码展示如下:

1. 得到Boss类对应的Class对象

2. 创建对象

3. 调用public的hi方法

  • 得到hi方法对象
  • 调用

4. 调用private static 方法

  • 得到 say 方法对象
  • 因为say方法是private, 所以需要暴破,原理和前面讲的构造器和属性一样
  • 因为say方法是static的,还可以这样调用 ,可以传入null

5. 在反射中,如果方法有返回值,统一返回Object , 但是它运行类型和方法定义的返回类型一致。

10、练习案例

练习一

通过反射修改私有成员变量com.hspedu.homework Homework01.java

1.定义PrivateTest类,有私有name属性,并且属性值为hellokitty

2.提供getName的公有方法

3.创建Private Test的类, 利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值

代码展示如下:

定义PrivateTest类,有私有name属性,并且属性值为hellokitty

提供getName的公有方法

创建PrivateTest的类,利用Class类得到私有的name属性,修改私有的name属性值,并调用getName()的方法打印name属性值


1. 得到 PrivateTest类对应的Class对象

2. 创建对象实例

3. 得到name属性对象

4. 暴破name

5. 得到getName方法对象

6. 因为getName() 是public,所有直接调用

练习二

利用反射和File完成以下功能Homework02.java

1.利用Class类的forName方法得到File类的class 对象

2.在控制台打印File类的所有构造器

3.通过newInstance的方法创建File对象, 并创建E:\mynew.txt文件

提示创建文件的正常写法如下:

File file = new File(" d:\aa.txt");//内存

file.createNewFile();//方法,才能真正地创建文件

代码展示如下:

利用Class类的forName方法得到File类的class 对象

在控制台打印File类的所有构造器

通过newInstance的方法创建File对象,并创建D:\mynew.txt文件

1. Class类的forName方法得到File类的class 对象

2. 得到所有的构造器

3. 指定的得到 public java.io.File(java.lang.String)

4. 得到createNewFile 的方法对象

今日份分享已结束,请大家多多包涵和指点!

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码