反射概述
想象一下,你在一个房间里边,但你看不见自己,也不知道自己是谁。这时候你面前有一个镜子,你可以通过镜子的反射来观察自己。反射就像这面镜子。它让你能够检查、分析、修改Java中的对象、类、方法等
使用情况:在通常情况下,我们编写的代码是固定的,执行的结果也是固定的。但是某些情况下我们不确定要创建什么类型的对象,也不确定要调用什么类型的方法。这些都通过运行时传递的参数决定。该机制叫做动态编程技术,也就是反射机制
反射就是在程序运行 过程中,对于任意一个类,都能知道这个类所有的属性和方法。对于任意一个对象,都能调用它的所有属性和方法。也就是可以动态创建对象并且动态调用方法的机制
三步
创建字节码文件对象 forName .class .getClass
调用对应类的构造方法 getConstructor
调用构造方法创建对象 newInstance
类:Class
构造方法:Constructor
方法:Method
字段:Field (属性)
实例:Instance
执行:Invoke
获取class对象的三种方式
想象一下你如何获得iphone手机的图纸
- 先找到一个iphone实体,然后逆向拆解绘制出图纸 这相当于对象.getClass() 需要先找到类new出来对象
- 直接向苹果公司索要 这相当于类名.class
- 从苹果公司偷 这相当于Class.forName(“包名.类名”)
第三种方法可以降低耦合度,我获得图纸和苹果公司无关,反射的类名即使不存在也不会报错,方便后期更改
对象.class获取对应的Class对象,如果不是对象.class就没有对应的Class对象
- 使用类名.class的方式可以获取对应类型的Class对象
可以是引用数据类型,包括数组、类、接口等,也可以是基本数据类型
当使用打印int.class时,int.class 实际上返回的是 Class 对象,但在打印时,会自动调用 toString() 方法将其转换为字符串,输出基本数据类型的名称。这是 Java 语言的一种语法糖,使得基本数据类型和引用数据类型在某些场景下可以统一对待。
在命令行中打印一个类的 Class 对象时,Java 解释器会将该对象的 toString() 方法调用,并打印其返回的字符串。在 Class 类中,toString() 方法返回的是该类的全限定名,即包名加类名。
在反射中,引用数据类型的 Class 对象可以用于创建实例、调用方法等操作,而基本数据类型的 Class 对象则无法直接进行实例化和方法调用
Class<Integer> integerClass = Integer.class;
sout(integerClass);
sout(Integer.class);
- 使用字符串Class.forName(“字符串”)的方式来获取参数指定类型的Class对象
字符串需要是全路径名(包名.类名)
Class aclass2 = Class.forName("java.long.String");
sout(aclass2);
- 使用引用/对象.getClass()方式可以获取对象运行时的类信息
这里的对象需要首先创建出来再使用,打印出来的是创建出对象的引用类型变量的包名+类名
List list = new ArrayList();
sout(list.getClass());
Class类的方法
- static Class<?>forName(String className)
用于获取参数指定对象的Class对象并返回 - T newInstance()
用于创建该Class对象表示类的新实例。就是创建了一个对象
//以无参对象创建构造Person类对象并打印
Class c1 = Class.forName("Person");//双引号中Person的值可以在运行中替换
System.out.println("无参方式创造的对象是:"+c1.newInstance());
获取单个指定的构造方法
Constractor类
java.lang.reflect.Contractor类 主要用于描述获取到的构造方法信息
Class类的常用方法
Constructor getConstructor(Class<?>…parameterTypes):获取此Class对象所表示的公共构造方法。其中参数可以有或者没有。括号必须内是Class类型,基本数据类型.class获得
Constructor<?>[] constructors = aclass.getConstructors() : 获取此Class对象所表示的所有公共构造方法
Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors():获取此Class对象所表示的所有构造方法
Constractor类的常用方法
T newlnstance(Onject…initargs) 使用此Constructor对象描述的构造方法来构造Class对象代表类型的新实例,给构造方法传参数,可以不传或者传多个。
获取属性
Field field = 字节码文件.getField
field.set(要赋值的对象,赋值给对象的值)
Object o = filed.get(类的名字)
获取方法
Method method = 字节码文件.getMethod(“方法名字”,需要方法的参数,class)
Object invoke = method.invoke(传的参数,又传的参数)
.class和.Class的区别
.class :创建对象的包装类,可以创建一个Class对象
int.class:就是int类型的Class对象引用,不是一个类,是一个引用,int类型是原始类型,用于获取基本数据类型int的Class对象
Integer是int类型的包装类,不是一个引用
.Class :用于返回对象的运行时的类的引用,表示某个对象的实际类型,用于获取某个对象的类信息