java之反射!!

反射

通俗的说就是你对象不管做的多么的严谨,只要通过反射就好比一面镜子,把你的对象拷过来,并且拷过来的对象,是任由我宰割的。

下面就简单的举个栗子:

第一步:创建要反射的对象:

这里我就写个超级简单的Student类,里面没有什么东西,2个属性。和一个私有的方法。

package javaClass;

public class Student {

    private String name;
    private int age;


    private Student() {
        super();
    }

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    private String studentInfo() {
        return "我的名字是:"+name;
    }



}
  • 有2个构造函数,一个是私有的,一个是公共的
  • 属性也是私有的哦
  • 其他都是get、set方法,就不说明了
  • 最后一个studentInfo方法是私有的
目的

我们要用反射,把Student类用私有的构造函数创建出来,并且不通过set方法给属性赋值。还要调用私有的studentInfo方法,看起来很酷!

第二步:获取字节码
  • 首先获取Student字节码

第一种方式:

Class clazz = Class.forName("javaClass.Student");

第二种方式:

    Class clazz=Student.class;

第三种方式:

    Student student = new Student();
    Class   clazz=student.getClass();

一般用第一种方式,最后一种方式,你都能创建对象了,你还用放射,明显是人才。第二种需要引入包名,而最第一种只需要字符串

第三步:创建对象

有了字节码,我们就等于拿到了克隆后的对象,现在怎么折腾都是由我们自己决定,现在我们要用私有的构造函数,来创建对象。

    //获取无参的私有构造函数
    Constructor cons = clazz.getDeclaredConstructor();
    //设置无视jvm规则
    cons.setAccessible(true);
    //创建对象
    Object  newInstance= cons.newInstance();

    //查看是否是Student对象
    System.out.println(newInstance instanceof Student);

输出结果:true

第四步:设置字段

        //通过字节码获取所有字段
        Field[] fields = clazz.getDeclaredFields();
        //遍历所有的字段
        for (Field field : fields) {
            //设置暴力
            field.setAccessible(true);
            //如果为年龄字段的话,就设置为整形
            if(field.getName().equals("age")) {
                field.set(newInstance, 23);
            }else {
                //这个对象就2个属性,那这个是放字符串的
                field.set(newInstance, "刘德华");
            }
        }
        Student s=(Student)newInstance;
        System.out.println(s.getName());
        System.out.println(s.getAge());

输出结果:刘德华、23

第五步:调用私有方法

我觉得这个操作最短,看代码:

        //获取studentInfo方法
        //这getDeclaredMethod方法有2个参数,一个参数为:方法名,第二参数是:该方法需要传入的参数
        //因为我们的studentInfo不需要传参,所有第二个参数就不需要填写
        Method method = clazz.getDeclaredMethod("studentInfo");
        //暴力设置
        method.setAccessible(true);
        //调用,返回一个结果
        Object invoke = method.invoke(newInstance);
        //看结果咯
        System.out.println(invoke);

输出结果:我的名字是:刘德华

猜你喜欢

转载自blog.csdn.net/qq_31403321/article/details/80412112