Java框架设计的灵魂--反射的基础知识

概念

  • 反射是可以在一个类运行的时候获取类的信息的机制,是Java语言的高级特性。
  • 为什么Java语言具有反射机制呢?
    • 因为在编写Java源代码(*.java)时类的信息通过编译器编译保存在Class对象中,而这个Class对象是在程序运行时被类加载器(ClassLoader)动态加载。
    • .类加载器(ClassLoader)将类对象中文件(*.class)中的成员变量,构造方法,成员方法等加载到内存中,在运行时阶段就可以动态地获取Class对象的信息以及动态操作Class对象的属性和方法了。
      Java框架设计的灵魂--反射的基础知识_第1张图片

获取Class对象的方式

  • 要应用反射机制,首先要获取由ClassLoader将字节码文件装载进内存的class类对象,获取该对象会有三种方式:
/**
 * 获了类对象的方式
 */
public class GetClassObject {

    public static void main(String[] args) throws ClassNotFoundException {

        // 第一种获取方式:Class.forName
        Class c1 = Class.forName("javademo202008.Reflect.Person");
        System.out.println(c1);

        // 第二种获取方式:类名.class
        Class c2 = Person.class;
        System.out.println(c2);

        // 第三种获取方式: 对象.getClass
        Person person = new Person();
        Class c3 = person.getClass();
        System.out.println(c3);

        // 验证三种方式获取的是否是同一对象
        System.out.println(c1 == c2 && c1 == c3);
    }
}
/**
 * 人员类
 */
class Person {
    private String name;
    private String age;

    public Person() {
    }

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

使用Class对象

获取到了内存中的Class类对象,接下来了解Class对象的各个功能 :

  1. 获取成员变量
方法 用途
getFields() 获得某个公有的属性对象
getField(String name) 获得所有公有的属性对象
getDeclaredField(String name) 获得某个属性对象
getDeclaredFields() 获得所有属性对象
  1. 获取构造方法
方法 用途
getConstructor(Class… parameterTypes) 获得该类中与参数类型匹配的公有构造方法
getConstructors() 获得该类的所有公有构造方法
getDeclaredConstructor(Class… parameterTypes) 获得该类中与参数类型匹配的构造方法
getDeclaredConstructors() 获得该类所有构造方法
  1. 获取成员方法
方法 用途
getMethod(String name, Class… parameterTypes) 获得该类某个公有的方法
getMethods() 获得该类所有公有的方法
getDeclaredMethod(String name, Class… parameterTypes) 获得该类某个方法
getDeclaredMethods() 获得该类所有方法
  1. 获取类名
方法 用途
getName() 获得类的完整路径名字
/**
 * 使用Class对象的各个功能
 */
public class ReflectGet {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
        // 获取Person的Class对象
        Class c = Person.class;

        // 1.获取所有成员变量
        Field[] fields = c.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.println(fields[i]);
        }
        // 私有成员变量赋值
        Field nameField= c.getDeclaredField("name");
        nameField.setAccessible(true);
        Person person = new Person();
        nameField.set(person,"Jack");
        System.out.println(person.toString());

        // 2.获取全参构造方法
        Constructor constructor = c.getConstructor(String.class,String.class);
        System.out.println(constructor);
        // 创建对象
        Object object = constructor.newInstance("Kate","19");
        System.out.println(object.toString());

        // 3.获取成员方法
        Method setNameMethod = c.getMethod("setName",String.class);
        Method setAgeMethod = c.getMethod("setAge", String.class);
        // 执行方法
        Person person1 = new Person();
        setNameMethod.invoke(person1,"Mike");
        setAgeMethod.invoke(person1,"12");
        System.out.println(person1.toString());

		// 4.获取类名
        String className= c.getName();
        System.out.println(className);
    }
}

反射的应用案例

- 编写一个程序框架,可以创建任意类的对象,并且执行任意方法
# 定义一个配置文件 config.properties 进行类名与方法调用的配置
ClassName=javademo202008.Reflect.Person
MethodName=say

# 通过该配置文件可以不改变代码,仅改变配置文件,即可实现类的更换
# ClassName=javademo202008.Reflect.People
# MethodName=say
- 自定义一个人员类
/**
 * 人员类
 */
public class Person {
    private String name;
    private String age;

    public Person() {
    }

    public Person(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public void say(){
        System.out.println("欢迎使用反射机制");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

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

- 框架代码
/**
 * 运用反射构建一个框架
 */
public class FrameWork {
    public static void main(String[] args) throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
        // 加载配置文件
        Properties properties = new Properties();
        ClassLoader classLoader = FrameWork.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream("config.properties");
        properties.load(inputStream);

        // 获取配置文件中定义类名与方法名
        String className = properties.getProperty("ClassName");
        String methodName = properties.getProperty("MethodName");

        // 加载类
        Class c = Class.forName(className);
        // 创建对象
        Object object = c.newInstance();
        // 获取方法对象
        Method method = c.getMethod(methodName);
        // 通过反射运行
        method.invoke(object);

    }

}

Java框架设计的灵魂--反射的基础知识_第2张图片

你可能感兴趣的:(java,java,反射)