Java高级进阶-反射
前言
反射是高级框架的基础,是进阶必备知识点之一,今天就来总结一下反射前前后后相关的知识点。
1.反射机制介绍
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
简单的说就是,一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。
2.反射作用
反射可以让我们在运行时获取类的属性,方法,构造方法、父类、接口等信息,通过反射还可以让我们在运行期实例化对象、调用方法、及时方法或属性是私有的也可以通过反射的形式调用。
3.创建和使用
3.1 获取class字节码对象
1.使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定名(必须添加完整包名)。
2.调用某个类的class属性来获取该类对应的Class对象。
3.调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法。
方法1:Class clazz = Class.forName("com.reflect.Student");
方法2:Class clazz1 = Student.class;
方法3:Student student = new Student();Class clazz2 = student.getClass();
3.2.获取class对象的属性、构造方法、普通方法
3.2.1 获取class对象的属性
Field[] allFields = clazz.getDeclaredFields();//获取class对象的所有属性
Field[] publicFields = clazz.getFields();//获取class对象的public属性
Field ageField = clazz.getDeclaredField("name");//获取class指定属性
Field desField = clazz.getField("age");//获取class指定的public属性
3.2.2 获取class对象的构造方法
Constructor[] allConstructors = clazz.getDeclaredConstructors();
//获取class对象的所有声明构造函数
Constructor[] publicConstructors = clazz.getConstructors();
//获取class对象public构造函数
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//获取指定声明构造函数
Constructor publicConstructor = clazz.getConstructor(String.class);
//获取指定声明的public构造函数
3.2.3 获取class对象的普通方法
Method[] methods = clazz.getDeclaredMethods();//获取class对象的所有声明方法
Method[] allMethods = clazz.getMethods();//获取class对象的所有public方法 包括父类的方法
Method method = clazz.getMethod("info", String.class);//返回次Class对象对应类的、带指定形参列表的public方法
Method declaredMethod = class1.getDeclaredMethod("info", String.class);//返回次Class对象对应类的、带指定形参列表的方法
3.2.4 获取class对象的信息
boolean isPrimitive = class1.isPrimitive();//判断是否是基础类型
boolean isArray = class1.isArray();//判断是否是集合类
boolean isAnnotation = class1.isAnnotation();//判断是否是注解类
boolean isInterface = class1.isInterface();//判断是否是接口类
boolean isEnum = class1.isEnum();//判断是否是枚举类
boolean isAnonymousClass = class1.isAnonymousClass();//判断是否是匿名内部类
boolean isAnnotationPresent = class1.isAnnotationPresent(Deprecated.class);//判断是否被某个注解类修饰
String className = class1.getName();//获取class名字 包含包名路径
Package aPackage = class1.getPackage();//获取class的包信息
String simpleName = class1.getSimpleName();//获取class类名
int modifiers = class1.getModifiers();//获取class访问权限
Class[] declaredClasses = class1.getDeclaredClasses();//内部类
Class declaringClass = class1.getDeclaringClass();//外部类
3.3 使用class对象
3.3.1 实例操作class对象方法
1.首先根据获取的class对象获取对应的Method方法集合或者获取指定方法
2.通过method方法对象调用invoke(Object obj,Object...params)方法来进行对对象进行修改赋值操作等等。第一个参数是传入的class对象,第二个是对应方法的参数列表。
// 生成新的对象:用newInstance()方法
Object obj = class1.newInstance();
//首先需要获得与该方法对应的Method对象
Method method = clazz.getDeclaredMethod("setAge", int.class);
//调用指定的函数并传递参数
method.invoke(obj, 28);
3.3.2 实例化操作class对象属性
1.通过Class对象的getFields()方法或者getField()方法获得指定方法,返回Field数组或对象。
2.Field提供了两组方法来读取或设置成员变量的值:
getXXX(Object obj):获取obj对象的该成员变量的值。此处的XXX对应8种基本类型。如果该成员变量的类型是引用类型,则取消get后面的XXX。
setXXX(Object obj,XXX val):将obj对象的该成员变量设置成val值。
//生成新的对象:用newInstance()方法
Object obj = class1.newInstance();
//获取age成员变量
Field field = class1.getField("age");
//将obj对象的age的值设置为10
field.setInt(obj, 10);
//获取obj对象的age的值
field.getInt(obj);
3.4 访问权限
在操作class对象方法时,会遇到无法访问的问题,这是因为,方法的访问权限为private,这时我们需要主动将访问权限修改,通过调用method对象的setAccessible(true)可以解决问题。
总结
反射机制是框架的支撑,在Java中有一套获取所有类字节码对象的API,而这正好为我们间接的操作对象提供了方便,同时反射降低了类与类的依赖性,不需要导包,即可创建对象。
参考: