反射的实现

1.获取类的字节码对象
//获取类的字节码对象
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式1:类名.Class
        Class<?> clazz1 = Student.class;

        //方式2:对象名.getClass()
        Student student = new Student();
        Class<?> clazz2 = student.getClass();

        //方式3:Class.forName("类的全路径名")
        Class<?> clazz3 = Class.forName("com.itheima1.Student");

        System.out.println(clazz1);
        System.out.println(clazz1 == clazz2);
        System.out.println(clazz2 == clazz3);
    }
}

2.获取Constructor【构造方法】对象

学生类

public class Student {
    private String name;
    private int age;

    //公共的无参构造方法
    public Student() {
        System.out.println("public...Student...无参构造方法");
    }

    //公共的有参构造方法
    public Student(String name, int age) {
        System.out.println("name的值为:" + name + "age的值为" + age);
        System.out.println("public...Student...有参构造方法");
    }

    //私有的有参构造方法
    private Student(String name) {
        this.name= name ;
        System.out.println("name的值为:" + name);
        System.out.println("private...Student...有参构造方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

获取Constructor对象的方法

//获取Constructor对象
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //首先得到Class对象再调用方法
        Class<?> clazz = Class.forName("com.itheima2.Student");
        //Constructor<T> getConstructor (class<?>... parameterTypes):返回单个公共构造方法对象【只能返回公共的,默认的等也不行】
        //Constructor<?> constructor = clazz.getConstructor();

        //constructor<T> getDeclaredConstructor (class<?>... parameterTypes):返回单个构造方法对象【可以返回私有的】
        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor);

        //Constructor<?>[] getConstructors ():返回所有公共构造方法对象的数组
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        //Constructor<?>[] getDeclaredConstructors ():返回所有构造方法对象的数组
        //Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
    }
}

打印结果:
-------------------------------------------------------------------------------------
public com.itheima2.Student(java.lang.String,int)
public com.itheima2.Student(java.lang.String,int)
public com.itheima2.Student()
2.1 Constructor对象的使用

根据指定的构造方法创建对象:
Class.newInstance();只能反射无参的构造器,需要构造器可见;
Constructor.newInstance();可以反射任何构造器,可以反射私有构造器

//反射获取Constructor对象并使用
//T newInstance (object. . . initargs):根据指定的构造方法创建对象
public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取Class对象
        Class<?> clazz = Class.forName("com.itheima2.Student");
        //2.获取构造方法对象【四种方法】
        Constructor<?> constructor1 = clazz.getDeclaredConstructor(String.class);
        //访问私有【其他修饰都能使用】的构造不能直接使用,getDeclaredConstructor()只能做访问
        //constructor.setAccessible(true):在创建学生对象之前临时取消访问检查【暴力反射】
        constructor1.setAccessible(true);
        //3.利用newInstance创建Student的对象
        Student student = (Student) constructor1.newInstance("张三");
        System.out.println(student);
        System.out.println("---------------------------------------------------------");
        //简写格式【不能获取私有方法,其他都可,默认访问空参构造】
        //1.获取Class对象
        Class<?> clazz1 = Class.forName("com.itheima2.Student");
        //2.在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象【已过时,做了解】
        Student student1 = (Student) clazz1.newInstance();
        System.out.println(student1);
    }
}

c
name的值为:张三
private...Student...有参构造方法
Student{name='张三', age=0}
---------------------------------------------------------
public...Student...无参构造方法
Student{name='null', age=0}
3.获取Field【成员变量】对象

学生类

public class Student {
    public String name;
    public int age;
    public String gender;
    private int money = 300;
}

获取Field【成员变量】对象的方法

//获取Field【成员变量】对象的方法
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class<?> clazz = Class.forName("com.itheima4.Student");
        //Field[] getFields ():返回所有公共成员变量对象的数组
        //Field[] fields = clazz.getFields();

        //Field[] getDeclaredFields ():返回所有成员变量对象的数组
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        // Field getField (string name):返回单个公共成员变量对象
        // 想要获取的成员变量必须是真实存在的
        //且必须是public修饰的
        Field f1 = clazz.getField("name");
        System.out.println(f1);
        // Field getDeclaredField (string name):返回单个成员变量对象
        Field f2 = clazz.getDeclaredField("money");
        System.out.println(f2);
    }
}

打印结果:
-------------------------------------------------------------------------------------
public java.lang.String com.itheima4.Student.name
public int com.itheima4.Student.age
public java.lang.String com.itheima4.Student.gender
private int com.itheima4.Student.money
public java.lang.String com.itheima4.Student.name
private int com.itheima4.Student.money
3.1 Field对象的使用

根据指定的构造方法创建对象:
void set (object obj, object value):给obj对象的成员变量赋值为value【如果私有则需要暴力反射】
object get (object obj)返回由该 Field表示的字段在指定对象上的值

//利用Field对象,获取值或者修改值
public class Demo2 {
    public static void main(String[] args) throws ReflectiveOperationException {
        // 1.获取class对象
        Class<?> clazz = Class.forName("com.itheima4.Student");
        //2.获取name这个Field对象
        Field f1 = clazz.getDeclaredField("name");
        Field f2 = clazz.getDeclaredField("age");
        Field f3 = clazz.getDeclaredField("money");
        f3.setAccessible(true);
        f1.setAccessible(true);//由于私有则需要暴力反射[在对象创建之前]
        //创建学生类的对象【如果空参构造私有,则要对成员方法暴力反射】
        Student student = (Student) clazz.getConstructor().newInstance();
        //3.利用set方法进行赋值
        //void set (object obj, object value):给obj对象的成员变量赋值为value
        f2.set(student, 20);
        f1.set(student, "张三");//等价于obj.setNome("张三");
        //4.获取属性值
        //object get (object obj)返回由该 Field表示的字段在指定对象上的值
        System.out.println(f1.get(student));
        System.out.println(f2.get(student));
        System.out.println(f3.get(student));
    }
}

打印结果:
-------------------------------------------------------------------------------------
张三
20
300
4 获取Method【成员方法】对象

学生类

public class Student {
    //有一个参数的show方法
    public void show(String n) { System.out.println("show..." + n); }

    //有两个参数的show方法
    private void show(String n, int m) {
        System.out.println("show..." + n +"..."+ m);
    }

    //有两个参数,有返回值的方法
    public int sum(int n, int m) {
        return m + n;
    }
}

反射获取学生类成员方法对象

<font color ="sky bule">反射获取Method【成员方法】对象
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> clazz = Class.forName("com.itheima5.Student");
        //Method[] getMethods ():返回所有公共成员方法对象的数组,包括继承的
        /*Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }*/
        //Method[] getDeclaredMethods ():返回所有成员防法对象的数组,不包括继承的
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        //Method getMethod (string name,class<?>... parameterTypes) :返回单个公共成员方法对象

        //Method getDeclaredMethod (string name,Class<?>... parameterTypes):返回单个成员方法对象
        Method show = clazz.getDeclaredMethod("show", String.class, int.class);
        System.out.println(show);
    }
}

打印结果:
-------------------------------------------------------------------------------------
public int com.itheima5.Student.sum(int,int)
public void com.itheima5.Student.show(java.lang.String)
private void com.itheima5.Student.show(java.lang.String,int)
private void com.itheima5.Student.show(java.lang.String,int)
4.1 Method对象的使用

method.invoke(student, 200, 100);

//反射获取成员方法使用
public class Demo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取类的字节码文件
        Class<?> clazz = Class.forName("com.itheima5.Student");

        //创建一个学生对象【调用方法使用】
        Student student = (Student) clazz.getConstructor().newInstance();

        //获取一个参数的show方法
        Method m1 = clazz.getMethod("show" , String.class);
        //System.out.println(m1);
        //执行
        m1.invoke(student,"hahah");//等价于obj.show (" hahah");

        //获取两个参数的show方法
        Method m2 = clazz.getDeclaredMethod("show", String.class, int.class);
        //System.out.println(m2);
        m2.setAccessible(true);
        //执行
        m2.invoke(student,"hehe",100);//等价于obj.show ("hehe",100);

        //获取两个int参数的sum方法[名称参数必须一致,不能少]
        Method m3 = clazz.getMethod("sum",int.class,int.class);
        //System.out.println(m3);
        //执行
        int sum = (int) m3.invoke(student, 200, 100);
        System.out.println(sum);
    }
}

打印结果:
-------------------------------------------------------------------------------------
show...hahah
show...hehe...100
300
5. 思路总结

<1>获取Constructor对象
1.创建Class方法【Class.forName(“类的全路径名”)】—通用

2.调用Class获取Constructor对象方法
先看修饰符
如果需要访问私有,则用带Declared的方法
否则两种类型的方法都可以使用

3.访问单个构造:看参数类型和个数填写方法参数得到Constructor对象
访问多个构造:直接调用方法得到Constructor对象

4.得到Constructor对象后使用
Class.newInstance();只能反射无参的构造器,需要构造器非私有;
Constructor.newInstance();可以反射任何构造器,可以反射私有构造器【创建学生对象前加取消访问检查方法】

<2>Constructor.newInstance()得到的对象传递到 Field对象调用的set();get();参数中执行方法
<3>Constructor.newInstance()得到的对象传递到Method对象调用的invoke();参数中执行方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陪雨岁岁年年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值