月黑雁飞高,反射全知道——剖析java反射机制
文章目录
- java 反射机制
- 反射机制概念
- java反射提供的功能
- 反射的基本使用
- 反射使用步骤(获取Class对象、调用对象方法)
- 反射使用
- 例子People
- 获取Class的三种方法(获取一个类的字节码对象)
- 获取一个类的所有信息
- 获取类中的变量(Field)
- 获取类中的方法(Method)
- 获取类的构造器(Constructor)
- 获取注解
- 通过反射调用方法
- 反射的应用场景
- Spring的IOC容器
- 反射+抽象工程模式
- JDBC加载数据库驱动类
- 反射的优缺点
- 反射的优点:
- 反射的缺点:
- 反射小问答
- 被反射的类是否一定需要无参构造方法?
- 反射总结
- 最后
java 反射机制
反射机制概念
- 在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。反射被视为动态语言的关键。简单来说反射就是java的各种成分映射成对应的java类。
- 通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。包括构造方法,属性,方法。
java反射提供的功能
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理。
java不是动态语言,但是通过反射机制实现动态机制。
反射的基本使用
java反射的主要组成
- Class:任何运行在内存中的所有类都是该Class类的实例对象,每个Class类对象内存都包含了本来的所有信息。通过反射干任何事情,都要先去找Class
- 类内部主要信息:
- Field:所有属性
- Constructor:所有构造方法
- Method:所有方法
- 类内部主要信息:
- Field:描述一个类的属性,内部包含了该属性的所有信息,例如数据类型,属性名,访问修饰符
- 类内部主要信息
- 标注在属性上的注解
- 属性名
- 属性的数据类型(boolean/double/int/String …)
- 属性访问修饰符(public/private/protected)
- 类内部主要信息
- Constructor:描述一个类的构造方法,内部包含了构造方法的所有信息,例如参数类型、参数名称、访问修饰符
- 类内部主要信息
- 构造方法的访问修饰符
- 构造方法的参数
- 参数的数据类型
- 参数的名称
- 标注在参数上的注解
- 类内部主要信息
- Method:描述一个类的所有方法(包括抽象方法),内部包含了该方法的所有信息,与Constructor类似,不同之处就是Method拥有返回值类型信息,因为构造方法是没有返回值的
- 类内部主要信息
- Constructor类内部主要信息
- 方法返回值类型(Int/double0
- 类内部主要信息
反射使用步骤(获取Class对象、调用对象方法)
- 获取想要操作的类的Class对象,它是反射的核心,通过Class对象我们可以任意调用类的方法
- 调用Class类中的方法,即就是反射的使用阶段
- 使用反射API来操作这些信息
反射使用
例子People
public class People {public String name;public int age;private double weight;public People(){}public People(String name,int age){this.name=name;this.age=age;}public void getInfo(){System.out.println(name+"的年龄是:"+age);}
}
获取Class的三种方法(获取一个类的字节码对象)
当使用javac编译后,就会产生一个.class文件,当字节码文件被装载进虚拟机执行的时候,会在内存中生成Class对象,包含了该类内部的所有信息,在程序运行阶段可以获取这些信息。
使用对象获取,使用对象的getClass获取
People people = new People(); Class clazz=people.getClass();
使用静态属性class
只有在编译前就已经声明了该类的类型才能获取到Class对象
Class clazz =People.class;
使用Class类的静态方法forName(通过类的全限定名获取该类的 Class 对象)
类要写全名
Class clazz = Class.forName("")
- 通过类的全路径名获取Class对象会抛出一个异常,要用try——catch来捕获异常。
当我们拿到class对象后就可以,获取类信息、调用其方法、获取其属性。
获取一个类的所有信息
Class对象中国包含了该类的所有信息,在编译期间我们能看到的信息及时该类的变量、方法、构造器,在运行时最常被获取的也是这些信息
每种功能内部以Declared细分为两类:
- 有Declared修饰的方法:可以获取该类内部包含的所有变量、方法和构造器,但是无法获取继承下来的信息
- 无Declared修饰的方法:可以获取该类中public修饰的变量、方法和构造器,以及获取继承下来的信息
如果要想获取类中所有的(包含继承)的变量、方法和构造器,则需要同时调用,并且用set集合存储他们获得的遍历,一方获取到相同的东西。
获取类中的变量(Field)
- Field[] getField():获取类中所有被public修饰的所有变量
- Field getField(String name):根据变量名获取类中的一个变量,改变了必须是被public修饰
- Field[] getDeclaredFields):获取类中所有的变量,但无法获取继承下来的变量
- Field getDeclaredField(String name):根据名称获取类中的变量,也无法获取继承下来的变量
获取类中的方法(Method)
- Method[] getMethods():获取类中被
public
修饰的所有方法 - Method getMethod(String name, Class…<?> paramTypes):根据名字和参数类型获取对应方法,该方法必须被
public
修饰 - Method[] getDeclaredMethods():获取
所有
方法,但无法获取继承下来的方法 - Method getDeclaredMethod(String name, Class…<?> paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法
获取类的构造器(Constructor)
- Constuctor[] getConstructors():获取类中所有被
public
修饰的构造器 - Constructor getConstructor(Class…<?> paramTypes):根据
参数类型
获取类中某个构造器,该构造器必须被public
修饰 - Constructor[] getDeclaredConstructors():获取类中所有构造器
- Constructor getDeclaredConstructor(class…<?> paramTypes):根据
参数类型
获取对应的构造器
如果父类的属性用protected修饰,利用反射是无法获取到的
获取注解
- Annotation[] getAnnotations():获取该对象上的所有注解
- Annotation getAnnotation(Class annotaionClass):传入
注解类型
,获取该对象上的特定一个注解 - Annotation[] getDeclaredAnnotations():获取该对象上的显式标注的所有注解,无法获取
继承
下来的注解 - Annotation getDeclaredAnnotation(Class annotationClass):根据
注解类型
,获取该对象上的特定一个注解,无法获取继承
下来的注解
只有注解的@Retension标注为RUNTIME时,才能通过反射获取到该注解
详情请点击:注解详情
通过反射调用方法
通过反射获取到某个Method类对象后,可以通过调用invoke方法执行
invoke(Oject obj, Object... args)
:参数``1指定调用该方法的**对象**,参数
2`是方法的参数列表值。- 如果调用的方法是静态方法,参数1只需要传入
null
,因为静态方法不与某个对象有关,只与某个类有关。
反射的应用场景
常见场景有三种:
- Spring实例化对象:当程序启动时,Spring会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中
- 反射+工程模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无序关注工厂类,工厂类可以应对各种新增类,反射可以使得程序更加健壮
- JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载启动类
Spring的IOC容器
在Spring中,经常会用到一个上下文配置文件applicationContext.xml里面就是关于bean的配置,查询启动时会读取该xml文件,解析出所有的标签,并实例化对象放入IOC容器中,IOC容器本质上就是一个工厂,通过工厂传入标签的id属性获取对应的实例。
Spring在实例化对象的过程经过简化后,可以理解为反射实例化对象的步骤
- 获取Class对象的构造器
- 通过构造器调用newInstance()实例化对象
当然Spring在实例化对象时,做了非常多额外的操作,才能让现在的开发便捷且稳定
反射+抽象工程模式
传统的工程模式,如果需要生产新的子类,就需要修改工厂类,在工厂类中增加新的分支。
利用反射和工厂模式相结合,在生产新子类时,工厂类不需要修改任何东西,可以专注于子类的实现,当子类确定下来时,工厂也就可以生成该子类了、
反射+抽象工厂的核心思想是:
- 在运行时通过参数传入不同子类的全限定名获取到不同的Class对象,调用newInstance()方法返回不同的子类。
JDBC加载数据库驱动类
在导入第三方库时,JVM不会主动去加载外部导入的类,而是等到真正使用时,才会去加载需要的类,正因为如此,我们可以在获取数据库连接时传入驱动类的全限定名,交给JVM加载该类
反射的优缺点
反射的优点:
- 增加程序灵活性:面对需求变更时,可以灵活地实例化不同的对象
- 增加扩展性,降低耦合性,无序提前硬编码目标类。
反射的缺点:
- 破坏类的封装性:可以强制访问private修饰的信息
- 性能损耗:反射相比直接实例化对象、调用方法、访问变量、中间需要很多检查步骤以及解析步骤,JVM无法对其进行优化
反射小问答
被反射的类是否一定需要无参构造方法?
不需要,因为有参数构造方法也可以反射。
反射总结
- 反射的思想:反射就想一面镜子,只有在运行时才能看到自己是谁,可以获取到自己的信息,甚至实例化对象
- 反射的作用:在运行时才确定实例化对象,使得程序更加的健壮,面对需求变更时,可以最大程度地做到不修改程序源码的情况下,应对不同的场景,实例化不同类型的对象。
- 反射的应用场景:Spring的IOC容器;反射+工厂模式,使得工厂类更加稳定;JDBC连接数据库时加载驱动类
- 反射的三个特点:增加程序的灵活性、破坏类的封装性以及性能损耗
最后
- 如果觉得看完有收获,希望能给我点个赞,这将会是我更新的最大动力,感谢各位的支持
- 欢迎各位关注我的公众号【java冢狐】,专注于java和计算机基础知识,保证让你看完有所收获,不信你打我
- 如果看完有不同的意见或者建议,欢迎多多评论一起交流。感谢各位的支持以及厚爱。
月黑雁飞高,反射全知道——剖析java反射机制相关推荐
- java 反射 Gc_深入浅析Java反射机制
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...
- 如何理解java反射_怎么理解java反射
怎么理解java反射? 概述 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个"反着来"的过程.我们通过new创建一 ...
- 如何优化java反射,如何有效地使用Java反射
反射是一种内置机制,用于在执行时对Java程序进行内省.它可以用来检查.修改和转换Java程序,而不会影响现有代码.这个强大的特性可以用来扩展程序的功能,在运行时检查类或对象的内部结构.本文试图探究其 ...
- java 防止反射_如何防止JAVA反射对单例类的攻击?
在我的上篇随笔中,我们知道了创建单例类有以下几种方式: (1).饿汉式; (2).懒汉式(.加同步锁的懒汉式.加双重校验锁的懒汉式.防止指令重排优化的懒汉式); (3).登记式单例模式; (4).静态 ...
- java 反射 本类,关于Java反射中基本类型的class有关问题
关于Java反射中基本类型的class问题 1. 基本类型的class和其对应包装类的class是不同的,所以在获得Method指定参数的时候,需要精确指定参数的类型,即 setInt(int x) ...
- java反射减少servlet_利用java 反射机制来实现一个servlet处理多种请求
如果我们想在一个servlet中处理多种请求(比如新闻的添加.删除),简单的可以在jsp提交表单的action路径中添加一个键值对,然后再servlet中接收后根据不同的值来调用不同的方法. jsp端 ...
- 【反射的使用】java反射的复习
反射 1.类加载器 1.1类加载 程序要使用一个类需要将类进行加载,连接,初始化 类加载:将class读入内存,创建一个class对象 类的连接:检查,协调 类的初始化:如果父类未初始化,会优先初始化 ...
- c 与java 反射性能_谈谈Java 反射的快慢
[相关学习推荐:java基础教程] 反射到底是好是坏 说到Java 中的反射,初学者在刚刚接触到反射的各种高级特性时,往往表示十分兴奋,甚至会在一些不需要使用反射的场景中强行使用反射来「炫技」.而经验 ...
- 如何理解java反射_如何理解java反射?
一.反射基本概念 反射之中包含了一个"反"的概念,所以要想解释反射就必须先从"正"开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产 ...
最新文章
- 一款可以在BCH链上养大熊猫的游戏——CryptoPandas
- 线程安全机制 python
- cnpm install -g live-server 安装服务
- 回顾 | 使用Visual Studio Code进行端到端应用程序开发
- 突破极限–如何将AeroGear Unified Push用于Java EE和Node.js
- android人脸识别demo_零门槛解决Windows人脸识别应用开发难题
- 打docker镜像_从安全到镜像流水线,Docker 最佳实践与反模式一览
- android应用程序的生命周期,Android应用程序的生命周期.doc
- Spring Boot 中文乱码问题解决方案汇总
- 基本地图加载完整示例
- 电子技术课程设计—交通灯控制系统设计
- 勒索病毒 -- “永恒之蓝”NSA 武器免疫工具
- 美股相关交易规则与业务知识
- Groovy的规则脚本引擎实战
- PLS-00103: Encountered the symbol “DECLARE“
- IDRAC 固件升级操:
- pythonfor循环功能手工皂_轻松领悟for循环,做一款Python版手账
- 端到端的图像压缩----《Channel-wise Autoregressive Entropy Models For Learned Image Compression》论文笔记
- 使用ffmpeg对视频进行画面裁剪
- 金山毒霸6 、金山网镖6 增强版 发布在即!!!
热门文章
- 在服务器里面修改油画,油画错误如何修改?
- 快速分析出德邦快递揽收后没有物流的单号
- Foreman部署裸机
- java基于SpringBoot+Vue+nodejs的演唱会话剧娱乐项目售票系统 element
- 解决Cannot find module ‘meteor/meteor’ ‘meteor/check’ ‘meteor/mongo’
- Shapefile文件读取-文件头
- 基于STM32L431单片机和NB-IOT技术的低功耗追踪器
- 【新技能get】如何通过地址查看附件企业基本信息?
- ABCDE-入栈,不可能的出栈次序
- [BZOJ 2085]POI2010 Hamsters