首先为什么要反射,当需要通过配置文件re.properties指定信息,创建Cat对象并调用方法hi

也就是说只通过修改外部配置文件,在不修改源码的情况下来控制程序,也符合OCP开闭原则,这种需求在框架里面很多。

一个例子

package top.ltyzqhh;

public class Cat {
    public Cat(){}
   // private String name ="Hello kitty" ;
    public String name ="Hello kitty" ;
    public Cat(String name){
        this.name=name;
    }
    public void  hi(){
        System.out.println("hi");
    }
    public void  cry(){
        System.out.println("555555");
    }
}

Untitled

package top.ltyzqhh.ReflectionOfjava;

import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class Reflection_of_java {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String method = properties.get("method").toString();
        //使用类加载机制
        //(1) 加载类,返回Class类型的对象
        Class cls = Class.forName(classfullpath);
        //(2) 通过cls得到加载的类top.ltyzqhh.Cat
        Object o = cls.newInstance();
        //(3) 通过cls得到所加载类top.ltyzqhhh.Cat的方法的对象
        Method method1 = cls.getMethod(method);
        method1.invoke(o);
    }
}

Java运行时反射机制的工作原理图

Untitled

反射相关的主要类:

  1. java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
  2. java.lang.reflect.Method:代表类的方法,Method方法表示某个类的方法
  3. java.lang.reflect.Field:代表类的成员变量,Field方法表示某个类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造方法,Constructor方法表示某个类的构造器方法
package top.ltyzqhh.ReflectionOfjava;

import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

public class Reflection01 {
    public static void main(String[] args) throws Exception{
        //1.使用Properties 类,可以读写配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();
        String method = properties.get("method").toString();

        //使用类加载机制
        //(1) 加载类,返回Class类型的对象
        Class cls = Class.forName(classfullpath);
        //(2) 通过cls得到加载的类top.ltyzqhh.Cat
        Object o = cls.newInstance();
        //(3) 通过cls得到所加载类top.ltyzqhhh.Cat的方法的对象
        Method method1 = cls.getMethod(method);
        method1.invoke(o);

        //Java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
        //得到name字段
        //getField不能得到私有的属性
        Field name = cls.getField("name");
        System.out.println(name.get(o));

        Constructor constructor = cls.getConstructor();//()可以指定构造器参数,没有则返回无参构造
        System.out.println(constructor);

        //这里传入的String.class,就是String类的Class对象
        Constructor constructor1 = cls.getConstructor(String.class);
        System.out.println(constructor1);

    }
}

反射优化

反射调用方法比普通调用方法会更慢

优化方法:关闭访问检查

  1. Method和Field、Construtor对象都有setAccessible()方法
  2. setAccessible作用是启动和禁用访问安全检查的开关
  3. 参数值为true表示反射的对象在使用时取消访问检查,提高反射效率。参数值为false则表示反射的对象执行访问检查