跳至主要內容

LincZero大约 3 分钟

反射 (Reflect)

各语言实现

反射库

  • Java
    • 有一个专门的包处理反射,配合注解使用
  • python
    • python作为脚本语言,根据类名字符生成类实例非常简单,类似java的Class.forName
    • python是一个脚本语言,它不像java一样有一个专门的包来处理反射
    • Python的内置函数提供了强大的反射机制
  • C
    • 自身不支持,也无特别好的库
    • boost库有但似乎说不好用,另一个就是UE4的C++也有反射:这个视频有说大致原理:https://www.bilibili.com/video/BV1yv4y1m77s/

反射类

反射机制

  • Java和C++一些相似的方法
    • java的 newInstance方法 对应C++中 虚拟构造器 的习惯用法。但有所不同
      • C++中的虚拟构造器不是一种语言特性,需要由专门的库支持
    • java的 Class类 与C++中的 type_info类 相似,java的 getClass方法 与C++中的 typeid 运算符等价
      • C++的type_info没Java的Class强大。只能以字符串的形式显示一个类型的名字,而不能创建那个类型的对象
  • C++本身没有自带的反射机制。至于虚拟构造器和type_info我也没用过、不懂

反射枚举

C++的X宏可以实现编译期反射,也有一些像better_enum之类的反射枚举库

相关知识

概念

参考:反射-01-问题提出open in new window

问题:BlindBox 类中有1024个open开头方法,方法会返回从1~1024之间的整数且不会重复,问哪个方法会返回 666(不能查看源码)

答案:如果有一个方法,能知道这个类中所有的方法并遍历,这么就可以解决这个问题

public class Test1 {
	public static void main(String[] args) throw InvocationTargetException, IllegalAccessExeption {
        // ……
    }
}

类的反射:反射即认清自己,让对象认清自己,知道对象的:

  • 类名
  • 父类
  • 接口
  • 成员变量
  • 方法

并非所有语言具备认清对象自己的能力,如C++。你只能知道类有什么方法,再去调用他。但不能去获取类有什么方法,再去调用。

反射API

反射机制允许程序在运行时借助 Reflection API 取得任何类的内部信息,并能直接操作对象的内部属性和方法(比如用字符串索引函数地址或类成员偏移地址)

原理

参考:反射-03-java反射原理open in new window

Java的反射枚举,原理大概是:把下面这些信息都给它记录下来,并且呢在类加载的时候把这些信息收集起来,放在一个特殊的对象中 —— InstanceKlass

  • 类名
  • 父类
  • 接口
  • 成员变量
  • 成员方法
  • 虚方法
  • __java__mirror,通过这个类方法,可以获取上面的信息

分类

  • 根据作用时期
    • 编译期反射。例如:C的X宏,可以类似这样的效果:在编译期间查枚举表
    • 运行期反射。例如:真正靠字符串进行反射的java、python的反射
  • 根据作用点
    • 类反射
      • 类对象反射
      • 类成员数据反射
      • 类成员函数反射
    • 枚举反射

和序列化、反序列化的联系

很多业务场景需要依赖反射机制,比如:RPC、Web MVC、对象序列化等