类反射有什么用呢? 今天学习了类反射的几个功能
1.通过类反射调用构造器
2.通过类反射调用普通函数
3.通过类反射访问成员变量
以下以UserModel 为例子
一.通过类反射调用构造器
正常的我们想要调用构造器怎么用?
//需要 1.拿到构造函数, 需要2.参数
UserModel user = new UserModel("Jack",22);
类反射也是如此,通过两大步骤 一步拿到构造函数 一步拿到参数
// 1. 只有是类反射 就要想办法拿到Class
Class c = Class.forName("dage.three.UserModel");
类反射提供一个方法可以拿到类的构造函数
c.getDeclaredConstructor(parameterTypes);
需要的参数是 形参 就是 下面代码 UserModel(String name, int age) 里面的String 和 int
public UserModel(String name, int age) {
this.name = name;
this.age = age;
}
所以 先把参数准备好
Class [] parameterTypes = new Class [2];
parameterTypes[0] = String.class;
parameterTypes[1] = int.class;
那么我们就的到了 构造函数 第一步完成
Constructor con=c.getDeclaredConstructor(parameterTypes);
第二步就是要提供实参给函数
主要的方法时 con.newInstance(initargs); 把实际参数放进去就好了
Object [] initargs = new Object[2];
initargs[0] = new String("Jack");
initargs[1] = new Integer(22);
Object obj=con.newInstance(initargs);
输出结果
那么要是调用空参构造呢? 空参简单点,参数给null 就好了代码如下
Constructor con=c.getDeclaredConstructor();
二.通过类反射调用普通函数
调用普通函数和调用构造函数原来差不多
我们要用类反射完成下列功能
UserModel user = new UserModel("Jack",22);
double sum1 =user.sum(10, 11.1);
也是一样的 我们需要拿到以下东西
1.user 对象 (就是前面讲的,通过构造器)
2.sum 函数
3.把参数给进去就好了
1.user对象就不再写了,前面的
2.拿到sum函数 通过 c.getDeclaredMethod(name, parameterTypes); 方法
name 是函数名, parameterTypes 是形参 就和前面的构造函数一样就是下面括号里面的形参 int 和 double
double sum(int a, double b){
return a+b;
}
给上形参就得到方法 完成两步了
Class parameterTypes[] = new Class [2];
parameterTypes [0] = int.class;
parameterTypes [1] = double.class;
Method m=c.getDeclaredMethod("sum", parameterTypes);
接下来就是第3步 提供实际参数 主要是 Method 里面的 这个方法
m.invoke(obj, args)
obj --- 对象 user
args --- 实参 10和11.1
把实参给进去就好了
Object args[] = new Object[2];
args[0] = 10;
args[1] = 11.1;
Object obj=m.invoke(user, args);
System.out.println("通过类反射调用sum函数结果"+obj);
System.out.println("通过对象调用sum函数结果"+sum1);
![这里写图片描述](https://img-blog.csdn.net/20170416201833304?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzM3NzIwOTA0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)``
三.通过类反射访问成员变量
-------------
//3通过类反射访问属性(成员变量)
@Test
public void fieldDemo() throws Exception{
Class c = Class.forName(“cn.hncu.reflect.three.UserModel”);
//3.1 访问静态变量
Field fld = c.getDeclaredField("MIN");
fld.set(null, 200);//给静态变量设置值 ---第1个参数为null
Object v1 = fld.get(null); //读取静态变量中的值
System.out.println(v1);
//3.2 访问非静态变量--引用类型
Field fld2 = c.getDeclaredField("str");
//Field fld2 = c.getField("str"); //WA: 权限不够
Object user = c.newInstance();
Object v2 = fld2.get(user); //user.str
System.out.println(v2);
//3.3 访问非静态变量--可以使用get(),也可以使用基本数据专用的get方法如getDouble()
Field fld3 = c.getField("value");
Object u = c.newInstance();
fld3.setDouble(u, 12.34); //u.value=12.34
double d = fld3.getDouble(u); //u.value
System.out.println("3: "+d);
}
4.. 暴力访问; 其实前面是不能访问私有(private) 的方法 只有我们打开暴力访问的开关就好了
//4 暴力访问
@Test
public void ViolenceAccess() throws Exception{
Class cls = Class.forName("cn.hncu.reflect.three.UserModel");
Method m = cls.getDeclaredMethod("sum", new Class[]{int.class,int.class});
m.setAccessible(true);//★打开暴力访问开门 ---该方法是AccessibleObject类中的,后者是Field、Method和Constructor的共同父类,因此都可采用这一句打开暴力访问开关
Object user = cls.newInstance();
Object resObj = m.invoke(user,new Object[]{10,20});
System.out.println(resObj);
}