上一篇文章中了解了Java的反射机制和获取类信息的一些基本方法,不过仅仅是获取了类的相关信息则不能价格Java反射机制的意义给体现出来,为此,我们还需要对其来进行使用。

1. 创建对象

我们先来创建一个测试类,如下:

public class Super {
    private int supPri = 1;
    int supPac = 2;
    protected double supPro = 3;
    public String supPub = "4";

    public Super(){}

    public Super(int supPri, int supPac, double supPro, String supPub) {
        this.supPri = supPri;
        this.supPac = supPac;
        this.supPro = supPro;
        this.supPub = supPub;
    }

    protected Super(int supPri, int supPac, double supPro){
        this(supPri,supPac,supPro,"4");
    }

    Super(int supPri, int supPac) throws Exception{
        this(supPri,supPac,3.0,"4");
    }

    private Super(int supPri){this(supPri,2,3.0,"4");}

    private void supPrivate(){}
    int supPackage(){return supPac;}
    protected double supProtected(){return supPro;}
    public String supPublic(){return supPub;}
}

(1)使用newInstance()方法创建对象

public class TestNewInstance {
    public static void main(String[] args) throws
            ClassNotFoundException,
            IllegalAccessException,
            InstantiationException {
        //获取Class对象
        Class c = Class.forName("com.zane.spbootdemo.reflecttest.Super");
        //通过class的newInstance()方法创建对象
        Super sup = (Super)c.newInstance();
        System.out.println(sup.supPac);
    }
}

输出结果为 : 2
上述中使用的newInstance()方法其 实际是与Super sup = new Super()等价。

(2)使用有参构造方法进行创建对象

该方法是使用Constructor中的newInstance(Object[] args)方法来创建对象的。

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestConstructor {
    public static void main(String[] args) throws
            ClassNotFoundException,
            NoSuchMethodException,
            IllegalAccessException,
            InvocationTargetException,
            InstantiationException {
        //获取Class对象
        Class c = Class.forName("com.zane.spbootdemo.reflecttest.Super");
        //通过构造方法来创建对象
        Constructor constructor = c.getDeclaredConstructor(new Class[]{int.class, int.class});
        Super sup = (Super) constructor.newInstance(new Object[]{21, 22});
        System.out.println(sup.supPackage());
    }
}
2. 修改属性

和上面类似,其对应的api在Field中。

public class TestField {
    public static void main(String[] args) throws
            ClassNotFoundException,
            IllegalAccessException,
            InstantiationException,
            NoSuchFieldException {
        //获取属性测试类
        //1.获取Class对象
        Class c = Class.forName("com.zane.spbootdemo.reflecttest.Super");
        //2.创建对象
        Super sup = (Super)c.newInstance();
        //通过属性名获取属性对象,这里的supPri为私有属性名
        Field supPri = c.getDeclaredField("supPri");
        //取消私有属性的访问权限
        supPri.setAccessible(true);
        //调用get(Object o)方法来获取对象o对应的属性值
        System.out.println("取消访问控制权限后访问supPri,值为:"+supPri.get(sup));
        //调用set(Object o,Object v)方法设置修改对象o的对应属性值
        supPri.set(sup,20);
        System.out.println("supPri修改后的值为:"+supPri.get(sup));

    }
}

结果:

取消访问控制权限后访问supPri,值为:1
supPri修改后的值为:20

在上述例子中,由于Super中的非private属性在创建对象后即可通过sup.xxx来获取,所以用非private修饰的属性来做例子没有意义,于是用private属性的supPri来做例子会比较合适。

通过Field类,我们可以修改属性的访问控制权限和属性值。

3. 调用方法

调用方法涉及到的类是Method类。

//反射机制获取方法的测试类。
public class TestMethod {

    public int add(int x, int y){
        return x+y;
    }
    public static void main(String[] args) throws
            IllegalAccessException,
            InstantiationException,
            NoSuchMethodException,
            InvocationTargetException {
       Class c = TestMethod.class;
       Object obj = c.newInstance();
       //通过方法名和方法参数来获取方法对象
        Method add = c.getDeclaredMethod("add", new Class[]{int.class, int.class});
        //通过invoke(Object o,Object[] args)来调用对象o的方法
        System.out.println("调用方法:add,输入值为3和4,结果为:"+
                add.invoke(obj,new Object[]{3,4}));

    }
}

结果:

调用方法:add,输入值为3和4,结果为:7

总结:这次价格Java反射机制重新复习了一边,解决了之前只有一个模糊的思想,由于之前老师讲的时候一笔带过,而且自己又不怎么理解,通过这次狠了心地学习,终于将常用地用法都掌握了。不过还是得多练多写代码才可以。