反射
概述
Java反射机制是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
想要解剖一个类,必须先要获取这个类的字节码文件对象。而解剖使用的就是Class类中方法,所以先要获取每一个字节码文件对应的Class类型的对象。
以上总结就是什么是反射。
反射就是吧Java类中各种成分映射成一个个的Java对象。
例如:一个类有:成员变量、方法、构造方法、包等信息,利用反射技术可以对一个类进行解剖,把每个组成部分映射成一个个的对象。
(其实:一个类中这些成员方法、构造方法,在加入雷中都有一个类来描述。)
反射机制的相关类
与Java反射相关的类如下:
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
下图是类的正常加载过程:反射的原理与Class对象
加载:Class对象是将class文件读入内存,并为之创建一个Class对象。
其中这个Class对象很特殊。
Class类的实例表示正在运行的Java应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。
Class没有公共构造方法。Class对象在加载类时有Java虚拟机以及调用类加载器中的defineClass方法自动构造的。也就是这不需要我们自己区处理创建,jvm已经帮我们创建好了。
获得类的相关方法
方法 | 用途 |
---|---|
asSubclass(Class<U>clazz) | 把传递的类的对象转换成代表其子类的对象 |
Cast | 把对象转换成代表类或是接口的对象 |
getClassLoader() | 获得类的加载器 |
getClass() | 返回一个数组,数组中国包含该类中所有公共类和接口类的对象 |
getDeclaredClasser() | 返回一个数组,数组中包含该类所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获取类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获取类的包 |
getSimpleName() | 获取类的名字 |
getSuperclass() | 获取当前类继承的父类的名字 |
getInterfaces() | 获取当前类实现的类或是接口 |
获取类中属性相关的方法
方法 | 用途 |
---|---|
getField(String name) | 获取某个公有的属性对象 |
getFields() | 获取所有公有的属性对象 |
getDeclaredField(String name) | 获取某个属性对象 |
getDeclaredFields() | 获取所有属性对象 |
获取类中注解相关的方法
方法 | 用途 |
---|---|
getAnnotation(Class<A>annotationClass) | 返回该类中与参数类型匹配的公有注解对象 |
getAnnotation() | 返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class<A>annotation() | 返回该类所有的注解对象 |
获取类中构造器相关的方法
方法 | 用途 |
---|---|
getConstructor(Class…<?>parameterTypes) | 获取该类与参数类型匹配的公有构造方法 |
getConstructors() | 获取该类的所有公有构造方法 |
getDeclaredConstructors(Class…<?>parameterTypes) | 获取该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获取该类所有构造方法 |
获取类中方法相关方法
方法 | 用途 |
---|---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
类中其他重要方法
方法 | 用途 |
---|---|
isAnnotation() | 如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型则返回true |
isAnonymousClass() | 如果是匿名类则返回true |
isArray() | 如果是一个数组类则返回true |
isEnum() | 如果是枚举类则返回true |
isInstance(Object obj) | 如果obj是该类的实例则返回true |
isInterface() | 如果是接口类则返回true |
isLocalClass() | 如果是局部类则返回true |
isMemberClass() | 如果是内部类则返回true |
Field类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
Method类
Method代表类的方法。
方法 | 用途 |
---|---|
invoke(Object obj, Object… args) | 传递object对象及参数调用该对象对应的方法 |
Constructor类
Constructor代表类的构造方法。
方法 | 用途 |
---|---|
newInstance(Object… initargs) | 根据传递的参数创建类的对象 |
反射的使用
1.获取Class对象的三种方式
1.1 Object ——> getClass();
1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
1.3 通过Class类的静态方法:forName(String className)(常用)
2.通过反射获取构造方法并使用
通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
1.获取构造方法:
1).批量的方法:
public Constructor[] getConstructors():所有”公有的”构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
2).获取单个的方法,并调用:
public Constructor getConstructor(Class… parameterTypes):获取单个的”公有的”构造方法:
public Constructor getDeclaredConstructor(Class… parameterTypes):获取”某个构造方法”可以是私有的,或受保护、默认、公有;
调用构造方法:
Constructor–>newInstance(Object… initargs)
2、newInstance是 Constructor类的方法(管理构造函数的类)
api的解释为:
newInstance(Object… initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象,并为之调用。
3.获取成员变量并调用
获取成员变量并调用:
1.批量的
1).Field[] getFields():获取所有的”公有字段”
2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
2.获取单个的:
1).public Field getField(String fieldName):获取某个”公有的”字段;
2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
设置字段的值:
Field –> public void set(Object obj,Object value):
参数说明:
1.obj:要设置的字段所在的对象;
2.value:要为字段设置的值;
由此可见
调用字段时:需要传递两个参数:
Object obj = stuClass.getConstructor().newInstance();//产生Student对象–》Student stu = new Student();
//为字段设置值
f.set(obj, “刘德华”);//为Student对象中的name属性赋值–》stu.name = “刘德华”
第一个参数:要传入设置的对象,第二个参数:要传入实参
4.获取成员方法并调用
获取成员方法并调用:
1.批量的:
public Method[] getMethods():获取所有”公有方法”;(包含了父类的方法也包含Object类)
public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
2.获取单个的:
public Method getMethod(String name,Class<?>… parameterTypes):
参数:
name : 方法名;
Class … : 形参的Class类型对象
public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
调用方法:
Method –> public Object invoke(Object obj,Object… args):
参数说明:
obj : 要调用方法的对象;
args:调用方式时所传递的实参;
由此可见:
m = stuClass.getDeclaredMethod(“show4”, int.class);//调用制定方法(所有包括私有的),需要传入两个参数,第一个是调用的方法名称,第二个是方法的形参类型,切记是类型。
System.out.println(m);
m.setAccessible(true);//解除私有限定
Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
System.out.println(“返回值:” + result);//