日常小知识学习
前言
Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查。被private封装的资源只能类内部访问,外部是不行的,但反射能直接操作类私有属性。反射可以在运行时获取一个类的所有信息,(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法。所以先要获取到每一个字节码文件对应的Class类型的对象。
一、通过反射获取到类信息
这里为通过反射拿一个类的基本信息,最常用的创建class对象时通过Class.forName()来获取,这个方式最高效也最安全,所以基本都在这么用。
1.获取包名、类名和完整类名
Class clazz = Class.forName("完整类路径");
clazz.getPackage().getName();//包名
clazz.getSimpleName();//类名
clazz.getName();//完整类名
2.获取成员变量定义信息
clazz.getFields();//获取所有公开的成员变量,包括继承变量
clazz.getDeclaredFields();//获取本类定义的成员变量,包括私有,但不包括继承的变量
clazz.getField("变量名");
clazz.getDeclaredField("变量名");
3.获取构造方法定义信息
clazz.getConstructor(Test4.class);//获取公开的构造方法
clazz.getConstructors();//获取所有的公开的构造方法
clazz.getDeclaredConstructors();//获取所有的构造方法,包括私有
clazz.getDeclaredConstructor(int.class,String.class);
4.获取方法定义信息
clazz.getMethods();//获取所有可见的方法,包括继承的方法
clazz.getMethod("方法名",int.class);//后面为方法的参数
clazz.getDeclaredMethods();//获取本类定义的的方法,包括私有,不包括继承的方法
clazz.getDeclaredMethod("方法名",int.class,String.class);//后面为方法的参数
5.创建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance();//执行有参构造创建对象
clazz.getConstructor(int.class,String.class);//获取构造方法
二、通过反射调用方法(练习)
这里有一个冒泡排序的算法,传入一个int数组,返回一个经过排序后int数组,
public static int[] bubbleShort(int[] arrayList){
for (int i = 0; i < arrayList.length-1; i++) {
for (int j = 0; j < arrayList.length-1-i; j++) {
int a = arrayList[j];
int b = arrayList[j+1];
if (a>b){
int c = a;
arrayList[j] = arrayList[j+1];
arrayList[j+1] = c;
}
}
}
return arrayList;
}
我想通过反射去调用这个方法来排序我的数组
第一步,创建该类的class对象,参数是填类的完整相对路径
Class<?> aClass = Class.forName("func.tools.ArraySort");
第二步,获取到该类想要调用的方法,第二个参数开始为方法的参数类型
Method method = aClass.getDeclaredMethod("bubbleShort", int[].class);
第三步,通过method.invoke()方法执行类方法,第一个参数是调用方法的参数类型,然后是要传入的数组a,返回一个实例
Object invoke = method.invoke(int[].class,a);
第四步,将object实例转换成int数组
int[] b = (int[]) invoke;
最后遍历就ok了
for (int i = 0; i < join.length; i++) {
System.out.print(join[i]+" ");
}