类反射学习(三) JAVA如何利用类反射调用普通函数、访问成员成员变量

来源:互联网 发布:传输网络结构 编辑:程序博客网 时间:2024/06/05 02:51

类反射有什么用呢? 今天学习了类反射的几个功能
1.通过类反射调用构造器
2.通过类反射调用普通函数
3.通过类反射访问成员变量

以下以UserModel 为例子

一.通过类反射调用构造器


正常的我们想要调用构造器怎么用?

//需要 1.拿到构造函数, 需要2.参数UserModel user = new UserModel("Jack",22);

类反射也是如此,通过两大步骤 一步拿到构造函数 一步拿到参数

// 1. 只有是类反射 就要想办法拿到ClassClass 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 --- 对象 userargs --- 实参 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);![这里写图片描述](http://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);    }
0 0