Java面试题-Java核心基础-第十天(反射)

目录

一、反射是什么?

二、反射的优缺点?

三、反射中常用的API

四、反射的应用场景


一、反射是什么?

就是一种可以动态获取类中所有信息以及可以操作类中的这些成员的这样一种能力。

正是由于这种特性才使得Java这种静态语言也具备一定的动态性。在框架底层得到大量使用

二、反射的优缺点?

优点:反射能让我们有了分析操作类的能力,可以获取到类中的所有结构

缺点:能让其避免掉泛型检查,因为反射是在运行时,而泛型检查在编译的时候,这样会有类型的安全隐患,另外反射还可以无视权限修饰符的限定,可以直接操作private的属性

三、反射中常用的API

首先要获取并操作那些类中的结构,首先就得获得字节码对象 也就是Class对象,利用类加载器将字节码装载成运行时数据区中的Class对象

有四种获取方式:

1. 调用对象的getClass()方法

2. 调用类的class属性

3. 通过全类名获取,调用Class类中的forName静态方法

4. 通过类加载器

ReflectionTest1.class.getClassLoader().loadClass("com.at guigi.java.Student")

获取到字节码对象之后,调用字节码的相应结构的get方法就能获取到相应的结构

获取相应结构:

获取基本结构:获取构造器、属性、方法  还可以获取一些详细结构,比如说属性上面的注解、方法上面的方法的修饰符,返回值类型,方法名,形参类型,抛出的异常,方法上面的注解,方法参数的注解都可以获取到

Field:

getFields():获取父类及本类中所有公共的属性

getDeclaredFields():获取到本类中所有的属性

getField(String name):获取父类及本类中名称为name的属性,注意只能获取公共的属性,如果属性不公共,那么会报错

getDeclaredField(String name):获取到本类中名称为name的属性,注意这里只是获取,如果对象要访问该属性,还得打开属性通道,field.setAccessible (true)

Method:

getMethods():获取父类及本类中所有公共的方法

getDeclaredMethods():获取本类中所有的方法

getMethod(String name,这里是Class类型的可变形参,也就是放方法形参的类型):获取本类及父类中,方法名为name,形参为指定形参的方法,注意只 能获取公共的方法

getDeclaredMethod(String name,这里是Class类型的可变形参,也就是放方法形参的类型):获取本类中方法名为name,形参为指定形参的方法

Class<?> clazz = Class.forName("com.atguigi.java.Student");
Method[] methods = clazz.getDeclaredMethods();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(clazz.getSimpleName()+"{\n");
for(Method method : methods){
//获取方法上面的注解
Annotation[] annotations = method.getAnnotations();
//System.out.println(annotations.length);
for(Annotation annotation : annotations){
stringBuilder.append(" "+annotation.toString()+"\n");
}
stringBuilder.append(" ");
// System.out.print(Modifier.toString(method.getModifiers()));
stringBuilder.append(Modifier.toString(method.getModifiers()));
//System.out.print(" ");
stringBuilder.append(" ");
//System.out.print(method.getReturnType().getSimpleName());
stringBuilder.append(method.getReturnType().getSimpleName());
// System.out.print(" ");
stringBuilder.append(" ");
//System.out.print(method.getName());
stringBuilder.append(method.getName());
// System.out.print("(");
stringBuilder.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
// for(Class clazz1 : parameterTypes){
// //System.out.print(clazz1.getSimpleName()+",");
// stringBuilder.append(clazz1.getSimpleName()+",");
// }
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
//System.out.println(method.getName()+""+parameterAnnotations.length);
for(int i=0;i<parameterTypes.length;i++){
System.out.println(method.getName()+":"+parameterTypes[i].getSimpleName()+":"+parameterAnnotations[i].length);
if(parameterAnnotations[i].length==0){
stringBuilder.append(parameterTypes[i].getSimpleName()+",");
}else{
for(int j=0;j< parameterAnnotations[i].length;j++){
stringBuilder.append(parameterAnnotations[i]+" ");
}
stringBuilder.append(parameterTypes[i].getSimpleName()+",");
}
}
if(parameterTypes.length!=0) {
stringBuilder.deleteCharAt(stringBuilder.length()-1);
}
stringBuilder.append(")");
Class<?>[] exceptionTypes = method.getExceptionTypes();
if(exceptionTypes.length!=0){
stringBuilder.append(" throws ");
for(Class clazz2 : exceptionTypes){
stringBuilder.append(clazz2.getSimpleName()+",");
}
stringBuilder.deleteCharAt(stringBuilder.length()-1);
}
stringBuilder.append("{}\n");
}
stringBuilder.append("}");
System.out.println(stringBuilder);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

获取方法的所有修饰符:method.getModifiers()      Modifier.toString(method.getModifiers())显示修饰符

获取方法的返回值:method.getReturnType() 获取到的是Class对象,可以调用.getSimpleName()获取到返回值的简单名字

获取方法上面的所有注解:Annotation[] annotations = method.getAnnotations()

获取方法名字:method.getName())

获取方法参数类型列表:Class[] parameterTypes = method.getParameterTypes() 不能获取到参数名

获取到方法参数上面所有的注解:Annotation[][] parameterAnnotations = method.getParameterAnnotations();

获取到方法上面的所有异常:Class[] exceptionTypes = method.getExceptionTypes();

Construct:

getDeclaredMethods():可以获取所有的构造器

getDeclaredMethod(构造器形参的参数类型列表):可以获取指定构造器

操作相应结构:

操作属性:

Class<?> clazz = Class.forName("com.atguigi.java.Student");
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
Object o = constructor.newInstance("张三", 1001);
Field name = clazz.getDeclaredField("name");
//访问私有属性,要打开通道
name.setAccessible(true);
//因为是私有方法,无法直接调用,报 IllegalAccessException错误
Object o1 = name.get(o);
System.out.println("对象o的name属性值是:"+o1);
System.out.println("将对象o的name属性值重新设置为:王五");
name.set(o,"王五");
System.out.println("对象o的name属性值是:"+o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

操作方法:

Class<?> clazz = Class.forName("com.atguigi.java.Student");
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
Object o = constructor.newInstance("张三", 1001);
//注意:只能使用getDeclaredMethod()才能获取私有的方法,否则报错NoSuchMethodException
Method method = clazz.getDeclaredMethod("food", String.class, Integer.class);
//调用方法
//method.invoke(o,"苹果",20); //因为是私有方法,无法直接调用,报 IllegalAccessException错误
//需要打开通道
method.setAccessible(true);
method.invoke(o,"香蕉",20);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

 操作构造器,通过构造器造对象:

Class<?> clazz = Class.forName("com.atguigi.java.Student");
Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
Object o = constructor.newInstance("张三", 1001);
//建议使用这种方式造对象,而非直接运行时对象调newInstance方法
Constructor<?> declaredConstructor = clazz.getDeclaredConstructor();
Object o1 = declaredConstructor.newInstance();
System.out.println(o1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

还可以直接用Class对象调用newInstances()方法,调用无参构造常见对象 

四、反射的应用场景

在Oracle官方说的是:

1. 可以通过解析xml创建对象

2. 可以枚举类中的所有属性,便于程序员开发

3. 可以访问私有结构,便于测试到所有结构

主要是框架中大量使用。

1. jdbc中先要加载驱动  就是利用反射加载  

public static final String DBDRIVER = "com.mysql.jdbc.Driver";

Class.forName(DBDRIVER) 这样能加载类 加载类中的静态结构 运行静态代码块

2. Spring中Xml创建Bean

<bean id="mystudent" class="com.bjpowernode.ba01.Student"><property name="name" value="张三"/><property name="age" value="20"/><property name="email" value="zs@qq.com"/>
</bean>

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

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

相关文章

openGauss学习笔记-107 openGauss 数据库管理-管理用户及权限-三权分立

文章目录 openGauss学习笔记-107 openGauss 数据库管理-管理用户及权限-三权分立107.1 默认的用户权限107.2 三权分立较非三权分立权限变化说明 openGauss学习笔记-107 openGauss 数据库管理-管理用户及权限-三权分立 默认权限机制和管理员两节的描述基于的是openGauss创建之初…

独立产品灵感周刊 DecoHack #053 - 有意思的地图网站

本周刊记录有趣好玩的独立产品设计开发相关内容&#xff0c;每周发布&#xff0c;往期内容同样精彩&#xff0c;感兴趣的伙伴可以 点击订阅我的周刊。为保证每期都能收到&#xff0c;建议邮件订阅。欢迎通过 Twitter 私信推荐或投稿。 周刊继续发布 ❤️ &#x1f4bb; 产品推…

redis缓存击穿/穿透/雪崩面试回答

面试官&#xff1a;什么是缓存穿透 ? 怎么解决 ? 候选人&#xff1a; 嗯~~&#xff0c;我想一下 缓存穿透是指查询一个一定不存在的数据&#xff0c;如果从存储层查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到 DB 去查询&#xff0c;可能导致…

部署Vue项目到githubPage中

上传Vue项目到githubPage 例如&#xff1a; 看我发布的地址 前提条件 1. github上有一个仓库并且仓库下有两个分支&#xff08;main 和 gh-pages&#xff09; 1.1 main分支保存你的vue项目源码&#xff08;react或者其他框架的都行&#xff09; 1.2 gh-pages分支保存的是你…

【C++ 学习】链接、作用域、内存管理

链接、作用域、内存管理 存储类别 int num 3;该声明创建了一个名为num的变量&#xff0c;变量值为3&#xff0c;num是这个变量的名字&#xff0c;也就是标识符。标识符是一个名称&#xff0c;一个合法的标识符必须以字母或者下划线&#xff08;_&#xff09;开头&#xff0c…

【C++入门篇】保姆级教程篇【上】

目录 一、第一个C程序 二、C命名空间 1&#xff09;什么是命名空间&#xff1f; 2&#xff09;命名空间的使用 3&#xff09; std库与namespace展开 4&#xff09;命名空间的嵌套使用 三、输入输出方式 四、缺省参数 1&#xff09;什么是缺省参数&#xff1f; 2&#xff0…

未能为 SSL/TLS 安全通道建立信任关系

在 Windows早期版本&#xff08;Windows server 2008&#xff09;上运行web请求相关代码&#xff0c;提示错误&#xff1a;未能为 SSL/TLS 安全通道建立信任关系。 打开IE直接访问相关网址&#xff0c;按照提示信任网站&#xff0c;安装证书&#xff1a; 选择&#xff1a;将所有…

【计算机网络】NAT机制的工作流程

网络地址转换&#xff08;NAT&#xff09;是一种将私有IP地址转换为公共IP地址的技术&#xff0c;它使得私有网络中的主机可以在互联网上与外部主机进行通信。NAT机制在路由器或专用NAT设备上配置&#xff0c;可以用于家庭、小型企业或大型企业的网络环境中。本文将总结NAT机制…

0基础学习VR全景平台篇第112篇:控制点和遮罩工具 - PTGui Pro教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 前情回顾&#xff1a;上节&#xff0c;我们用PTGui拼接了一张全景图&#xff0c;全景编辑器里的各项功能帮助我们进行了初步的检查和编辑。 之后我们需要使用【控制点】和【遮罩…

pytorch 入门 (四)案例二:人脸表情识别-VGG16实现

实战教案二&#xff1a;人脸表情识别-VGG16实现 本文为&#x1f517;小白入门Pytorch内部限免文章 参考本文所写记录性文章&#xff0c;请在文章开头注明以下内容&#xff0c;复制粘贴即可 &#x1f368; 本文为&#x1f517;小白入门Pytorch中的学习记录博客&#x1f366; 参…

华为数通方向HCIP-DataCom H12-831题库(多选题:21-40)

第21题 网络管理员A希望使用ACL匹配特定的路由条目,请问以下哪些路由条目将被图中的ACL规侧匹配? acl number 2000 rule 10 permit source 10.0.0.0 0.0.6.0A、10.0.0.1/32 B、10.0.0.0/24 C、10.0.1.0/24 D、10.0.2.0/24 答案: 解析: 通配符十进制6转换二进制为00000110,…

提升药店效率:山海鲸医药零售大屏的成功案例

在医药行业中&#xff0c;特别是医药零售领域&#xff0c;高效的药品管理和客户服务至关重要。随着科技的飞速发展&#xff0c;数字化解决方案已经成为提高医药零售管控效率的有效工具之一。其中&#xff0c;医药零售管控大屏作为一种强大的工具&#xff0c;正在以独特的方式改…

Qml的知识点

QML&#xff08;Qt Meta-Object Language&#xff09;是一种用于创建用户界面的声明性编程语言&#xff0c;它通常用于构建Qt应用程序的前端界面。以下是一些关于QML的重要知识点&#xff1a; 1. QML基础: - QML是一种声明性编程语言&#xff0c;用于描述用户界面的结构和行…

互联网Java工程师面试题·Spring篇·第二弹

目录 3、Beans 3.1、什么是 spring bean&#xff1f; 3.2、spring 提供了哪些配置方式&#xff1f; 3.3、spring 支持集中 bean scope&#xff1f; 3.4、spring bean 容器的生命周期是什么样的&#xff1f; 3.5、什么是 spring 的内部 bean&#xff1f; 3.6、什么是 spri…

ONEPIECE!程序环境和预处理——C语言最终章

时间过得飞快呀&#xff0c;从第一篇blog到现在&#xff0c;已经有三四个月的时间了&#xff0c;而我们终于也迎来了C语言的最终章——程序环境和预处理&#xff01;加油吧朋友们&#xff0c;ONEPIECE就在眼前~ 目录 一、程序的"翻译环境"和"运行环境" 二…

Biotech - 环状 mRNA 的 LNP 递送系统 与 成环框架

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/133992971 环状 RNA&#xff08;或 circRNA &#xff09;是一种单链 RNA&#xff0c;与线性 RNA 不同&#xff0c;形成一个共价闭合的连续环。在环…

Hadoop+Hive+Spark+Hbase开发环境练习

1.练习一 1.数据准备 在hdfs上创建文件夹&#xff0c;上传csv文件 [rootkb129 ~]# hdfs dfs -mkdir -p /app/data/exam 查看csv文件行数 [rootkb129 ~]# hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l 2.分别使用 RDD和 Spark SQL 完成以下分析&#xf…

python爬虫入门(三)正则表达式

开源中国提供的正则表达式测试工具 http://tool.oschina.net/regex/&#xff0c;输入待匹配的文本&#xff0c;然后选择常用的正则表达式&#xff0c;就可以得出相应的匹配结果了 常用的匹配规则如下 模  式描  述\w匹配字母、数字及下划线\W匹配不是字母、数字及下划线的…

零代码编程:用ChatGPT多线程批量将PDF文档转换为word格式

pdf2docx是Python的一个库&#xff0c;可以很方便的将PDF文档转换为word格式&#xff0c;首先安装这个库。 然后在ChatGPT中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;要完成一个文档格式转换的任务&#xff0c;具体步骤如下&#xff1a; 打开F盘的Books文件…

强化学习代码实战(1)

机器人领域&#xff1a;控制&#xff0c;规划&#xff0c;感知等都可以用&#xff0c;可以把它作为一个优化过程&#xff0c;那么任何需要优化的问题都可以用它解决。 1.应用 深度学习&#xff1a;智能感知&#xff0c;解决智能如何理解这个世界的问题。 强化学习&#xff1a…