3.反射

一、反射是什么

反射,指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法。这种动态获取信息,以及动态调用对象方法的功能,叫做java语言的反射机制;简而言之,反射就是获取Class类对象及其内部信息(方法,属性,构造函数)以及反向控制实例对象的能力

二、反射原理

我们编写的java项目,在运行前会编译源文件成为一个个.class文件(字节码文件)
在运行时,这些字节码文件会被ClassLoader加载器加载到JVM中,然后通过jvm指令运行起来;此时JVM会在内存中创建一个Class对象
我们可以通过Class对象获取Field(成员变量),Methos(成员方法),Constructor(构造函数)

三、反射使用

1.Class对象的获取
class对象的获取一般有三种

System.out.println(Test.class);
System.out.println(new Test().getClass());
System.out.println(Class.forName("com.atguigu.test8.Test"));
运行结果:

2.获取类的成员变量信息

方法    用途
getField(String name)    获得某个公有属性对象
getFields()    获得所有公有属性对象
getDeclaredField(String name)    获得某个属性对象(public和非public)
getDeclaredFields()    获得所有属性对象(public和非public)

public class Test {
    private String name;
    public String email;
    public String getName(){
        return this.name;
    }
    public void setName(String name){
        this.name = name;
    }
    public static void main(String[] args) throws Exception {
        Class clz = Class.forName("com.atguigu.test8.Test");
        Test test = (Test) clz.newInstance();
        Field[] fields = clz.getDeclaredFields();
        for(Field field : fields){
            System.out.println(field);
        }
    }
}

打印结果
在这里插入图片描述

3.获取类的方法
方法    用途
getMethod(String name,Class…<?>parameterTypers)    获得该类的某个公有方法
getMethods()    获得该类的所有公有方法
getDeclaredMethod(String name,Class…<?>parameterTypers)    获得该类的某个方法(public和非public)
getDeclaredFields()    获得所有属性对象(public和非public)

public class Test {
    private String name;
    public String email;
    public String getName(){
        return this.name;
    }
    public void setName(String name){
        this.name = name;
    }
    public static void main(String[] args) throws Exception {
        Class clz = Class.forName("com.atguigu.test8.Test");
        Test test = (Test) clz.newInstance();
        Method[] methods = clz.getMethods();
        for(Method method : methods){
            System.out.println(method);
        }
    }
}

打印结果
在这里插入图片描述

3.获取类的构造函数
方法    用途
getConstructor(Class…<?>parameterTypers)    获得类中与参数类型匹配的公有构造方法
getConstructors()    获得该类的所有公有构造方法
getDeclaredConstructor(Class…<?>parameterTypers)    获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()    获得该类所有构造方法

public class Test {

    private String name;
    public String email;
    public Test(String name,String email){}
    public Test(){}

    public static void main(String[] args) throws Exception {
        Class clz = Class.forName("com.atguigu.test8.Test");
        Test test = (Test) clz.newInstance();
        Constructor[] constructors = clz.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println(constructor);
        }
        Constructor constructor = clz.getConstructor(String.class,String.class);
        Test test1 = (Test) constructor.newInstance("小明","123@qq.com");
        System.out.println(test1);
    }

打印结果
在这里插入图片描述

四、反射实例

这里介绍一下Spring的IOC原理

1、Spring 在项目启动的时间通过读取xml中配置的bean的路径,

2、然后通过Class.forName 读取class 到类加载器,

3、然后通过反射创建所有的bean实例并保存到容器中,启动容器之后,

4、在项目中可以直接获取bean对象。

下面是大概实现此过程的代码

public class ClazzTest {
  public static void main(String[] args){
      try {
          Map<String,Object> container = new HashMap<>();
          //1.读取配置
          InputStream in = ClazzTest.class.getResourceAsStream("/beans.properties");
          Properties property = new Properties();
          property.load(in);
          //2.反射创建对象
          Set<Object> keySet = property.keySet();
          for (Object key : keySet) {
              // 2.1 获取类的全路径
              String classStr = (String) property.get(key);
              // 2.2 加载class 到虚拟机
              Class<?> beanClazz = Class.forName(classStr);
              // 2.3 获取缺省的构造函数
              Constructor<?> declaredConstructor = beanClazz.getDeclaredConstructor();
              // 2.4 创建实例
              Object o = declaredConstructor.newInstance();
              container.put((String) key,o);
          }
          // 3.获取实例
          Npc npc = (Npc) container.get("npc");
          System.out.println(npc == null);
      } catch (Exception e) {
          e.printStackTrace();
      }
  }
}

 

posted @ 2022-09-09 09:09  随遇而安==  阅读(23)  评论(0编辑  收藏  举报