反射
1. 反射
1.1 昨日回顾
Java文件包含Java程序的所有内容
类 {
成员变量, 成员方法,构造方法
}
Java文件编译之后==> .class字节码文件 (二进制文件)
.class字节码文件同样包含Java程序的所有内容
类 {
成员变量,成员方法,构造方法
}
.class字节码文件会在程序的加载阶段占用内存的【方法区】空间
我们可以认为当前在方法区占用的内存空间是包含整个Java程序的所有内容。
Class Field Method Constructor Annotation
... 不定长参数
数据类型指定,但是参数个数不指定!!!
参数传入到方法以内,会变成一个数组形式。
1.2 万物皆对象
这里需要将.class字节码文件占用的【方法区】内存空间看作是一个【对象】
当前.class字节码文件占用的内存空间,可以看做是一个对象,重点是这是一个什么数据类型???
每一个.class对应的都是一个Java类
占用的内存空间对应的就是一个Java类
该数据类型是Class类型
class 类名 {
成员变量
成员方法
构造方法
注解
}
当前.class字节码文件占用的【方法区】内存空间,我们可以看做是一个Class类型对象占用空间。
这里是对于数据类型的封装过程。
所有的方法都有返回值类型,方法名和形式参数列表。所以所有的方法,都可以看做是一个类 Method类型
所有的成员变量都有数据类型,成员变量名字。所有的成员变量都可以看做是一个类
Field类型
所有的构造方法,方法名一致!!!形式参数列表不一致,所有的构造方法都可以看做一个类 Constructor类
Annotation 注解类
1.3 Class类型获取
static Class Class.forName(String packageAndClassName)
throw ClassNotFoundException;
根据指定的完整包名.类名获取对应的Class对象,并且当前方法有加载指定类的能力。
Class 类名.class;
通过类名获取Class对象,这里相对于获取的是对应数据类型的Class属性,通常用于数据类型约束。
Class 类对象.getClass();
通过类对象调用getClass()方法,获取当前类对象对应的Class对象。
package com.qfedu.a_reflect;
/**
* 获取Class类对象演示
* @author Anonymous
*
*/
public class GetClassObject {
public static void main(String[] args) throws ClassNotFoundException {
/*
* Class.forName(String 完整的包名.类名);
*/
Class<?> cls1 = Class.forName("com.qfedu.a_reflect.Person");
/*
* 通过类名.class获取当前类对应的 Class对象
*/
Class<Person> cls2 = Person.class;
/*
* 通过类对象.getClass() 方法获取当前类对象对应的Class对象
*/
Class<? extends Person> cls3 = new Person().getClass();
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
System.out.println(cls1 == cls2);
System.out.println(cls2 == cls3);
System.out.println(cls3 == cls1);
}
}
1.4 通过Class对象获取Constructor对象
Constructor[] getConstructors();
获取类内的所有非私有化构造方法类对象数组,返回值类型是Constructor数组类型
Constructor[] getDeclaredConstructors();
【暴力反射】
获取类内所有构造方法类对象数组,包含私有化构造方法。
Constructor getConstructor(Class... initParameterTypes);
获取类内指定数据类型的非私有化构造方法类对象
Class... initParameterTypes 不定长参数,要求数据类型是Class类型
例如:
cls.getConstructor();
==> 无参数构造方法 Person();
cls.getConstructor(int.class);
==> int类型参数构造方法 Person(int);
cls.getConstructor(int.class, String.class);
==> int类型和String类型参数构造方法 Person(int, String);
Constructor getDeclaredConstructor(Class... initParameterTypes);
【暴力反射】
获取类内的指定数据类型构造方法,包括私有化构造方法
Class... initParameterTypes 不定长参数,要求数据类型是Class类型
例如:
cls.getDeclaredConstructor(String.class);
==> 私有化构造方法 private Person(String);
/*
Class[] getParameterTypes();
*/
1.5 Constructor对象创建对应类对象
构造方法类对象 Constructor是通过Class对象得到的,Class对象对应的类,如果需要创建对象就可以通过Constructor对象调用方法来创建。
Object newInstance(Object... initParameters);
通过Constructor对象调用,需要参数是一个不定长参数Object类型,是针对当前Constructor对象,对应构造方法的实际参数。
Object... initParameters 不定长参数,要求是Object类型,参数个数不确定
例如:
Constructor con1 = cls.getConstructor();
==> 无参数构造方法 Person();
con1.newInstance();
Constructor con2 = cls.getConstructor(int.class, String.class);
==> int类型和String类型参数构造方法 Person(int, String);
con2.newInstance(10, "苟磊");
1.6 通过Class对象获取Method对象
Method[] getMethods();
获取当前类内的所有非私有化成员方法,包含从父类继承而来子类可以使用的成员方法
Method[] getDeclaredMethod();
【暴力反射】
获取当前类内的所有自有成员方法,包含私有化成员方法,但是不包含从父类继承而来的方法。
Method getMethod(String methodName, Class... parameterTypes);
根据指定的方法名和对应的形式参数列表数据类型,选择当前类内的非私有化成员方法类对象。
String methodName 方法名
Class... parameterTypes 当前方法运行需要的形式参数列表数据类型
例如:
cls.getMethod("game");
==> public void game();
cls.getMethod("game", String.class);
==> public void game(String);
Method getDeclaredMethod(String methodName, Class... parameterTypes);
【暴力反射】
根据指定的方法名和对应的形式参数列表数据类型,获取类内的成员方法,包含私有化成员方法
String methodName 方法名
Class... parameterTypes 当前方法运行需要的形式参数列表数据类型
/*
getReturnType();
*/
1.6 Method对象执行方法
Object invoke(Object obj, Object... values);
通过Method类对象调用,执行Method类对象对应的成员方法
Object obj 是执行当前方法的类对象,谁的方法
Object... values 是当前方法执行所需参数列表
1.7 通过Class对象获取Field对象
Field[] getFields();
获取类内的所有非私有化成员变量
Field[] getDeclaredFields();
【暴力反射】
获取类内的所有成员变量,包括私有化成员变量
Field getField(String fieldName);
根据指定的成员变量名字获取对应的非私有化成员变量对象
Field getDeclaredField(String fieldName);
【暴力反射】
根据指定的成员变量名字获取对应的成员变量对象,包括私有化成员变量
1.8 Field对象操作方法
Object get(Object obj);
获取指定类对象中对应成员变量的数据
void set(Object obj, Object value);
使用指定数据,赋值对应类对象中的成员变量数据
/*
String getName();
Class getType();
*/
1.9 给予暴力反射权限操作方法
AccessibleObject对象.setAccessible(boolean flag);
给予单个的AccessibleObject对象给予操作权限
public static void setAccessible(AccessibleObject[] array, boolean flag);
给予AccessibleObject对象数组全体操作权限。
AccessibleObject
是Field, Method, Constructor这些类的父类,表示可以被授予权限的。
网友评论