反射
官方的概念是:Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
还有一种说法就是:反射就是把一个类的各个组成部分(成员方法,成员变量和构造方法等)分别各自封装为一个对象。
个人理解:反射就是虚拟机把.class文件加载到内存中,于此同时,会帮.class文件生成一个Class对象,而这个Class对象把.class文件的所有成员方法,成员变量和构造方法等封装成一个对象作为成员变量,然后通过Class对象获取对应的成员变量(对象),然后操作这些对象,来操作类的成员等。
(补充一点:在JVM看来,所有的方法或变量,都是普通的方法或普通变量,万物皆普通。)
反射的出来的Class对象
Class对象能操作类的那些东西呢?Class对象能操作方法对象(Method),变量对象(Field),构造函数对象(constructor)。
获取Class对象的方法:
- Class.forName(“类的全路径名”):全路径名,即src目录下一级目录开始
- 类名.class
- 类对象.getClass()
1、Class对象操作方法对象(Method)的一些方法
- Method getMethod(String methodName):获取public修饰的一个方法,返回方法的对象
- Method [ ] getMethods():获取所有public修饰的方法,返回一个数组,存储所有方法对象
- Method getDeclareMethod(String methodName):获取任何修饰符修饰的一个方法,返回方法对象
- Method [ ] getDeclareMethod():获取任何修饰符修饰的所有方法,返回数组,存储所有方法对象
2、Class对象操作变量对象(Field)的一些方法
- Field getField(String valueName):获取public修饰的一个变量,返回变量对象
- Field [ ] getFields():获取public修饰的所有变量,返回数组,存储所有变量对象
- Field getDeclareField(String valueName):获取任何修饰符修饰的一个变量,返回变量对象
- Field [ ] getDeclareFields():获取任何修饰符修饰的所有变量,返回数组,存储所有变量对象
3、Class对象操作构造函数(Constructor)的一些方法
- Constructor getConstructor(String constructorName):获取public修饰的一个构造函数,返回构造函数的对象
- Constructor[] getConstructors(String constructorName):获取public修饰的所有构造函数,返回一个数组,存储构造函数对象
-
- Constructor getDeclareConstructor(String constructorName):获取public修饰的一个构造函数,返回构造函数的对象
- Constructor[] getDeclareConstructors(String constructorName):获取public修饰的所有构造函数,返回一个数组,存储构造函数对象
反射操作类
获取到封装好的类成员等对象之后,就可以获取他们,改变他们了。
1、操作变量(变量对象下的一些操作)
- length:变量对象的总数。
- int getModifiers():获取变量的修饰符,返回一个int类型的。需要通过Modifiers.toString(int num)转换成字符串类型。
Modifier.toString(c.getModifiers())
-String getType():返回类型的名称(如果是引用类型,返回全路径名)。简化名称需要用getSimpleName()。f.getType().getSimpleName()
- String getName():返回变量名。
- Object get(Object o):返回变量值。传入的是该类的实例化对象。可以使newInstance得到的对象,也可以是new该类得到的对象。
2、操作方法(方法对象下的一些操作)
- length:方法对象的总数。
- int getModifiers():获取方法的修饰符,返回一个int类型的。需要通过Modifiers.toString(int num)转换成字符串类型。
Modifier.toString(c.getModifiers())
- String getReturnType():返回方法的返回类型。
- String getName():返回方法的名称。简化名称需要用getSimpleName()。
f.getType().getSimpleName()
- int getParameterCount():返回方法参数的个数。
- Class [ ] getParameterTypes():返回方法的所有参数类型,封装为Class对象。通过遍历,获取每个参数的类型。
3、操作构造函数(构造函数对象下的一些操作)
- int getModifiers():获取构造函数的修饰符,返回一个int类型的。需要通过Modifiers.toString(int num)转换成字符串类型。
Modifier.toString(c.getModifiers())
- String getName():获取构造函数的名字。简化名称需要用getSimpleName()。
f.getType().getSimpleName()
- int getParameterCount():返回构造函数参数的个数。
- Class [ ] getParameterTypes():返回构造函数的所有参数类型,封装为Class对象。通过遍历,获取每个参数的类型。
- newInstance(Object…param):创建一个反射的类的对象。如果是无参构造,也可以使用Class对象中的newInstance来创建一个类对象。
4、操作类本身
- int getModifiers():获取构造函数的修饰符,返回一个int类型的。需要通过Modifiers.toString(int num)转换成字符串类型。
Modifier.toString(c.getModifiers())
- String getName():获取类名称。简化名称需要用getSimpleName()。
f.getType().getSimpleName()
代码
package cn.reflectDemo;
import java.lang.reflect.*;
public class reflect {
/**
* 反射机制 反编译成java文件 获取类的所有属性和方法 包括静态的
* @author 一只搬砖的码蚁
* @date 2020/9/14 13:31
*/
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
test1();
}
//第一种获取反射的方法Class.forName
public static void test1() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
//Class.forName 获取Class对象
Class c = Class.forName("cn.reflectDemo.User");
//获取所有属性
Field[] fs=c.getDeclaredFields();
//实例化
Object o = c.newInstance();
//获取类的修饰符
System.out.println("类的修饰符:"+Modifier.toString(c.getModifiers()));
System.out.println("类的名称:"+c.getSimpleName());
System.out.println("属性个数:"+fs.length);
// System.out.println(fs);
//显示所有属性名和属性值 以及修饰符
for (Field f : fs) {
f.setAccessible(true);
System.out.println("-----------------------------");
System.out.println("变量修饰符:"+Modifier.toString(f.getModifiers()));
System.out.println("变量的类型:"+f.getType().getSimpleName());
System.out.println("变量名:"+f.getName());
System.out.println("变量值:"+f.get(o));
}
//获取所有方法
Method[] declaredMethods = c.getDeclaredMethods();
System.out.println("------------------------------------");
System.out.println("方法个数:"+declaredMethods.length);
for (Method declaredMethod : declaredMethods) {
declaredMethod.setAccessible(true);
System.out.println("-----------------------------");
System.out.println("方法修饰符:"+Modifier.toString(declaredMethod.getModifiers()));
System.out.println("方法返回类型:"+declaredMethod.getReturnType());
System.out.println("方法名:"+declaredMethod.getName());
Class[] params = declaredMethod.getParameterTypes();
Parameter[] parameters = declaredMethod.getParameters();
for (Class param : params) {
System.out.println("方法参数类型:"+param);
}
System.out.println("方法参数个数:"+declaredMethod.getParameterCount());
// System.out.println(declaredMethod.invoke(o));
}
}
}