?虚假的标题

?真正的标题

《关于这个人明明自己都搞不懂这个知识点却妄想给别人讲清楚这档事》

要介绍反射机制,首先需要了解Java中的一个类——

Class<T>类

T-由此Class对象建模的类的类型。例如User.class的类型为Class<User>

Class类的实例表示正在运行的Java应用程序中的类和接口

上面两句看不懂没关系,因为这是我从API文档里复制的,不过下面这句话还是需要理解一下?

如果说T类是它的实例 t“图纸” 的话,Class<T>类就是 T 类的“图纸”


这个类存储了指定类型的类的成员变量成员方法构造方法,并封装了可以获取这些成员的方法

例如我们有一个类User,那么Class<User>类型的实例中就存储了User类的成员变量,成员方法,构造方法。

反射机制就是通过类对象来获取指定类的成员,使得可以在代码在运行的时候去操作这些成员。(不知道自己在说啥)


获取Class对象

要拿到一个类的类对象,主要有三种方法:

1.使用Class类的静态方法forName(String className);
1
Class<User> clazz=Class.forName("com.dataerror.User");//参数为目标类的全类名
2.目标类名.class
1
Class<User> clazz=User.class;
3.Object类的getClass方法()
1
2
User user=new User();
Class<User> clazz=user.getClass();

使用Class对象操作类的成员

1.获取成员属性

可以使用Class对象的以下方法获取成员属性:

1.Field getField(String name);获取目标类中的名为name且访问权限为public的属性

1
2
3
4
5
Class<User> clazz=User.class;
//获取User类中的名为username且访问权限为public的属性
Field f=clazz.getField("username");
//打印f会在控制台输出该属性的访问权限,类型,所在类.属性名
Sysout(f);

2.Field[] getFields();获取目标类中所有访问权限为public的属性

1
2
3
4
5
//返回存储了目标类所有属性的数组
Field[] fields=clazz.getFields();
for (Field field : Fields) {
     System.out.println(field);
}

3.Field getDeclaredField(String name);获取目标类中的名为name的属性

4.Field[] getDeclaredFields();获取目标类中所有属性

上述两种方法的用法和前两个基本相同,只是3,4方法会无视访问权限,获取所有已经定义的属性

2.获取构造方法

1.Constructor<T> getConstructor(Class<?>… parameterTypes);

返回类 T 中参数列表为parameterTypes且访问权限为public的构造方法,parameterType为0个或多个类对象

1
2
3
4
Class<User> clazz=User.class;
Constructor c=clazz.getConstructor();//获取User类中的无参构造方法
获取User类中参数列表为(String username,String password)的构造方法
Constructor c1=clazz.getConstructor(String.class,String.class);

2.Constructor<?>[] getConstructors();返回该Class对象所有的public的构造方法

3.Constructor<T> getDeclaredConstructor(Class<?>… parameterTypes);通过参数列表类型获得该Class对象的构造方法

4.Constructor<?>[] getDeclaredConstructors();返回该Class对象的所有的构造方法

逐渐偷懒

上述方法的使用方式和获取属性的使用方式都差不多,所以就不赘述了(话说连使用方法都找不到的话还是先去加强基础吧(别打我呜呜))

获取到构造方法后就可以通过得到的Constructor对象的newInstance();方法来创建实例

1
2
Constructor c1=clazz.getConstructor(String.class,String.class);
User user=c1.newInstance("admin","123456");
3.获取成员方法

1.Method getMethod(String name,Class<?>… parameterTypes);获取目标类中名为name,参数列表类型为parameterTypes的成员方法

获取到Method对象后可以使用Method类中的invoke(Object obj,Object… args)来执行方法

1
2
3
4
5
6
7
8
9
10
//类user中定义了如下方法
public String func(int a,String b){
    return "我要"+a+b;
}
//-----------------------------------------------------------------------------------------------------
//获取上述方法
Class<User> clazz=User.class;//获取User的类对象
User user=clazz.newInstance();//通过User的类对象来创建一个User的对象
Method m=clazz.getMethod("func",int.class,String.class);//获取上述方法
m.invoke(user,1,"份色图");//执行方法,必须存在一个实例(user)才可以执行方法

和上面一样,获取成员方法也有另外三种方法(越来越懒)

Method[] getMethods();获取目标类的所有public方法

Method getDeclaredMethod(String name,Class<?>… parameterTypes);获取目标类名为name,参数列表为paramTypes的方法

Method[] getDeclaredMethods();获取目标类的所有方法

拿到这些成员之后能干什么?

相信不管是谁,看到这里一定一脸懵逼吧(你不会真以为有人看到这里吧)

明明可以直接使用new关键字来创建对象,使用Getter Setter来设置属性,使用obj.method();来调用方法,为什么还要费那么大劲去特意获取这些成员呢?

看看下面这个例子,应该能帮助你理解

写的有点烂,求轻喷qaq