那位先生

个人站

前世五百次回眸,才能换得今生的一次擦肩而过。


秒懂反射

1.概述

反射就是通过对象的字节码生成对应的对象及对象的各个成员。一个类的成员包括:包名package,构造器constructor,属性字段field,普通方法method. 因此类的字节码同样是由这四样构成,反射的目的也是获取这四个成员。

2.获取字节码的三种方式

① :类.Class;
② 对象.getClass();
③ Class.forName(“类的全路径”);
以Student为例子:

package com.example.demo.reflect1.study;

@Data
public class Student {
    private String name;
    public int age;
    private double score;

    public Student() {}
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void helloWorld() {
        System.out.println("hello world!");
    }

    public void hiGirl(String name) {
        System.out.println("good night:" + name + "!");
    }
}

获取字节码的三种方式:

①:Class class1 = Student.class;

②:Student student = new Student();Class class2 = student.getClass();

③:Class class3 = Class.forName("com.example.demo.reflect1.study.Student");

3.通过反射生成对象

1.获取构造器

创建一个类是通过构造方法来创建,因此需要先获取字节码中的构造器。获取构造器的方法:
1.获取有(无)参数的构造器:class.getConstructor(Class<?>… parameterType);
2.获取一个类的所有构造器:class.getConstructors();
栗子:
获取所有构造器:Constructor[] constructor3 = class3.getConstructors();
获取构造器(无参数)–Student(){}构造函数也没有参数:Constructor constructor1 = class3.getConstructor();
获取构造器(有参数),从Student(String name, int age) {} 的构造函数可以看出参数为String.class和int.class.: Constructor constructor2 = class3.getConstructor(String.class,int.class);

2.通过构造器创建对象

通过调用newInstance()方法生成实例对象。

Student student1 = (Student) constructor1.newInstance();
Student student2 = (Student) constructor2.newInstance("xie",25);

3.总结

整体流程就是:获取类的字节码–>通过字节码获取构造器–>通过构造器调用newInstance()生成实例对象.

4.通过反射获取对象的成员变量

通过字节码获取成员属性信息,包括修饰符,类型,名称,值。以 Class studentClass = Class.forName("com.example.demo.reflect1.study.Student");为例子。

1.获取属性字段信息

1.获取所有的属性字段:Field[] fields = studentClass.getDeclaredFields();
2.获取属性为age的字段:Field field = studentClass.getDeclaredField("age");

2.获取属性所在类的全路径

获取属性字段所在类的全路径:String classPath = field.getDeclaringClass().getTypeName();

3.获取修饰符

int mod = field.getModifiers();
修饰符:0.默认,1.public,2.private,4.protected

4.获取字段类型

Class type = field.getType();
字段类型:int、double、String等。

5.获取字段名

String fieldName = field.getName();

6.获取字段的值

当修饰符为private的时候不能直接获取,需要添加fieldAge.setAccessible(true);否则会显示权限不足。

Student student = (Student) studentClass.newInstance();  
Object value =field.get(student);
System.out.println("age字段值:"+value);
Field fieldAge = studentClass.getDeclaredField("name");
//私有属性字段需添加:fieldAge.setAccessible(true);
Object valueName =fieldAge.get(student);
System.out.println("nmae字段值:"+valueName);

7.结果

上面的输出结果为:
类的全路径:com.example.demo.reflect1.study.Student
权限类型:1
字段名:age
数据类型:int
age字段值:20
name字段值:null

5.通过反射调用方法

通过反射调用类里面的成员方法:

Class studentClass = Student.class;
Student student = (Student) studentClass.getConstructor().newInstance();

1.获取类里面的所有方法

Methods[] methods = studentClass.getMethods();
它获取的方法还包括它父类的所有方法,比如在这里它不仅包括Student中的helloWorld()和hiGirl(String Name),还包括Object的8个方法即toString(),equal,notify()等;

2.获取和调用某个方法

1.获取某个方法:
Method method =studentClass.getMethod("方法名",方法的参数对应的类型...);
2.调用某个方法:
method.invoke(方法所在的对象实例,方法参数...); 比如,获取并调用student的helloWorld()方法:

Method method1 = studentClass.getMethod("helloWorld");
method1.invoke(student);

获取并调用student的hiGirl(String name)方法:

Method method2 = studentClass.getMethod("hiGirl",String.class);
method2.invoke(student,"y");

3.结果:

hello world!
good night:y!

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
你说多少就多少

比五毛钱特效专业哦