目录
一、Class类的使用与动态加载类
package com.study.reflect;
/**
* 类功能描述:Class类的使用
*
* @author:***
* @createTime:2018/11/12 16:33
*/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//任何一个类都是Class的实例对象,这个实例对象有三种表达方式 c1==c2==c3
//c1 c2 c3 是DemoA的类类型(class type)
DemoA demoA = new DemoA();
Class c1 = demoA.getClass();
Class c2 = DemoA.class;
//Class.forName动态加载类(运行时加载类) new是静态加载类(编译时加载类)
Class c3 = Class.forName("com.study.reflect.DemoA");
System.out.println(c1 == c2 && c2 == c3 && c3 == c1); //输出true
//通过类类型创建该类的对象实例 newInstance()
((DemoA) c1.newInstance()).print(); //输出print
}
}
class DemoA {
void print() {
System.out.println("print");
}
}
二、JAVA获取方法、成员变量、构造函数信息
class DemoA {
public void print() {
System.out.println("print");
}
public static void main(String[] args) throws NoSuchMethodException {
DemoB.printMethodInfo("hello");
DemoB.printMethodInfo(1);
}
}
class DemoB {
public static void printMethodInfo(Object obj) throws NoSuchMethodException {
Class objClass = obj.getClass();
//java.lang.String
System.out.println("类名称为:" + objClass.getName());
//String
System.out.println(objClass.getSimpleName());
//getMethod获取所有public的函数,包括父类继承而来的
System.out.println(objClass.getMethod("toString").getName());
//getDeclaredMethod获取的是所有该类自己声明的方法,无视访问权限
System.out.println(objClass.getDeclaredMethod("toString").getName());
//方法也是对象
//遍历方法列表
Method[] methods = objClass.getMethods();
for (Method method : methods) {
System.out.print(method.getName() + "(");
//遍历参数名,并打印
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
System.out.print(parameterTypes[i].getSimpleName());
if (i < parameterTypes.length - 1) {
System.out.print(",");
}
}
System.out.println(")");
}
//成员变量也是对象
//遍历成员变量列表
Field[] fields = objClass.getFields();
for (Field field : fields) {
//遍历成员遍历并打印
System.out.println(field.getType() + " " + field.getName());
}
//构造函数也是对象
//构造函数列表
Constructor[] constructors = objClass.getConstructors();
for (Constructor constructor : constructors) {
//构造函数方法名
System.out.print(constructor.getName());
//遍历构造函数参数列表
Class[] typeParameters = constructor.getParameterTypes();
System.out.print("(");
for (int i = 0; i < typeParameters.length; i++) {
//打印参数名
System.out.print(typeParameters[i].getSimpleName());
if (i < typeParameters.length - 1) {
System.out.print(",");
}
}
System.out.println(")");
}
}
}
三、方法反射的基本操作
class DemoC {
public void test(int a, int b) {
System.out.println(a + b);
}
}
class DemoA {
/**
* 反射就是将类别的各个组成部分进行剖析,可以得到每个组成部分,就可以对每一部分进行操作
* 在比较复杂的程序或框架中来使用反射技术,可以简化代码提高程序的复用性。
* 我对invoke理解:运用反射,可以避过编译时检查,
* 像方法test可以通过入参的形式调用,如果没有test这个方法,使用传统的调用方式,编译都无法通过
* 可以编写统一的反射方法,当增加或删除某个方法时,这个反射方法就不用做一些变动了,可以简化代码提高复用。
* 类 方法 字段等都是在运行时才会执行,通过invoke方法,可以绕过编译。
* 例如 ArrayList<String> arr = new ArrayList<>(); 可以通过反射绕过编译,从而添加进其他类型的值
* Method method = arr.getClass().getMethod("add", Object.class);
* method.invoke(arr, 20);
* System.out.println(arr); 输出20,已经添加进去了
*/
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
DemoC democ = new DemoC();
Method test = democ.getClass().getMethod("test", new Class[]{int.class, int.class});
Object object = test.invoke(democ, new Object[]{10, 20});
}
}