反射机制介绍

阅读:264

目录介绍

  • 01.Java反射机制原理
  • 02.Java反射机制的功能
  • 03.Java反射的应用
  • 04.Class与.class文档
  • 05.反射之动态交互
  • 06.使用反射的初衷

01.Java反射机制原理

  • 反射的原理是什么?
    • 反射是为了能够动态的加载一个类,动态的调用一个方法,动态的访问一个属性等动态要求而设计的。它的出发点就在于JVM会为每个类创建一个java.lang.Class类的实例,通过该对象可以获取这个类的信息,然后通过使用java.lang.reflect包下得API以达到各种动态需求。
    • 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

02.Java反射机制的功能

  • Java反射机制的功能有哪些?
    • 1.在运行时判断任意一个对象所属的类。
    • 2.在运行时构造任意一个类的对象。
    • 3.在运行时判断任意一个类所具有的成员变量和方法。
    • 4.在运行时调用任意一个对象的方法。
    • 5.生成动态代理。
  • 反射的组成
    • 由于反射最终也必须有类参与,因此反射的组成一般有下面几个方面组成:
      • 1.java.lang.Class.java:类对象;
      • 2.java.lang.reflect.Constructor.java:类的构造器对象;
      • 3.java.lang.reflect.Method.java:类的方法对象;
      • 4.java.lang.reflect.Field.java:类的属性对象;
    • 反射中类的加载过程
      • 根据虚拟机的工作原理,一般情况下,类需要经过:加载->验证->准备->解析->初始化->使用->卸载这个过程,如果需要反射的类没有在内存中,那么首先会经过加载这个过程,并在在内存中生成一个class对象,有了这个class对象的引用,就可以发挥开发者的想象力,做自己想做的事情了。

03.Java反射的应用

  • Java反射的应用
    • 1.逆向代码 ,例如反编译
    • 2.与注解相结合的框架 例如Retrofit
    • 3.单纯的反射机制应用框架 例如EventBus
    • 4.动态生成类框架 例如Gson
  • 反射的作用有哪些
    • 前面只是说了反射是一种具有与Java类进行动态交互能力的一种机制,在Java和Android开发中,一般情况下下面几种场景会用到反射机制.
      • 需要访问隐藏属性或者调用方法改变程序原来的逻辑,这个在开发中很常见的,由于一些原因,系统并没有开放一些接口出来,这个时候利用反射是一个有效的解决方法
      • 自定义注解,注解就是在运行时利用反射机制来获取的。
      • 在开发中动态加载类,比如在Android中的动态加载解决65k问题等等,模块化和插件化都离不开反射,离开了反射寸步难行。
  • 反射的用途
    • 官方解释:反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。这是一个相对高级的特性,只有那些语言基础非常扎实的开发者才应该使用它。如果能把这句警示时刻放在心里,那么反射机制就会成为一项强大的技术,可以让应用程序做一些几乎不可能做到的事情。

04.Class与.class文档

  • Java 在真正需要某个类时才会加载对应的.class文档,而非在程序启动时就加载所有类,因为大部分时候我们只需要用到应用程序部分资源,有选择地加载可以节省系统资源
  • java.lang.Class 的实例代表 Java 应用程序运行时加载的 .class 文档,类、接口、Enum等编译过后,都会生成 .class 文档,所以 Class可以用来包含类、接口、Enum等信息
  • Class 类没有公开的构造函数,实例是由 JVM 自动产生,每个 .class 文档加载时, JVM 会自动生成对应的 Class 对象
    • 可以通过 Object 的 getClass() 方法或者通过 .class 常量取得每个对象对应的 Class 对象。如果是基本类型,可以使用对象的包装类加载 .TYPE 取得 Class 对象
    • 例如,使用 Integer.TYPE 可取得代表 int 基本类型的 Class,通过 Integer.class 取得代表 Integer.class 文档的 Class
    • 在取得 Class 对象后,就可以操作 Class 对象的公开方法取得类基本信息
    package net.zhifou.demo;
    public class Student {
    	public static void main(String[] args) {
    		Class cl = Student.class;
    		System.out.println("类名称:"+cl.getName());
    		System.out.println("简单类名称:"+cl.getSimpleName());
    		System.out.println("包名:"+cl.getPackage());
    		System.out.println("是否为接口:"+cl.isInterface());
    		System.out.println("是否为基本类型:"+cl.isPrimitive());
    		System.out.println("是否为数组对象:"+cl.isArray());
    		System.out.println("父类名称:"+cl.getSuperclass().getName());
    	}
    }
    

    • 输出结果为
    类名称:net.zhifou.demo.Student
    简单类名称:Student
    包名:package net.zhifou.demo
    是否为接口:false
    是否为基本类型:false
    是否为数组对象:false
    父类名称:java.lang.Object
    

  • Java 在真正需要类时才会加载.class文档,即在生成对象时才会加载.class文档。如果只是使用类声明了一个变量,此时并不会加载.class文档,而只是让编译程序检查对应的 .class 文档是否存在。
    • 例如,在 Stduent 类中定义了 static 静态区域块,在首次加载 .class 文档时会被执行(这是默认情况下,也可以指定不执行)
    public class Student {
    	static {
    		System.out.println("载入了 Student.class 文档");
    	}
    }
    

    • 再来测试加载顺序
    package net.zhifou.demo;
    
    public class Main {
    	public static void main(String[] args) {
    		Student student;
    		System.out.println("声明了 Student 变量");
    		student=new Student();
    		System.out.println("生成了 Student 实例");
    	}
    }
    

    • 输出结果为
    声明了 Student 变量
    载入了 Student.class 文档
    生成了 Student 实例
    

05.反射之动态交互

  • 反射是一种具有与类进行动态交互能力的一种机制,为什么要强调动态交互呢
    • 动态加载,也就是在运行的时候才会加载,而不是在编译的时候,在需要的时候才进行加载获取,或者说你可以在任何时候加载一个不存在的类到内存中,然后进行各种交互,或者获取一个没有公开的类的所有信息,换句话说,开发者可以随时随意的利用反射的这种机制动态进行一些特殊的事情。博客

06.使用反射的初衷

  • 使用反射的初衷是什么
    • 反射的初衷不是方便你去创建一个对象,而是让你在写代码的时候可以更加灵活,降低耦合,提高代码的自适应能力。

赞赏支持


精彩留言

发表评论