Java 和 C# 中的反射机制
一、反射简介 反射是一种程序动态访问修改其状态或行为的机制。具体来说,反射提供了在程序运行时对代码进行操作的手段。 反射提高了程序的灵活性和扩展性,能使程序员通过字符串动态地实现程序的修改。它降低了代码间的耦合度,可以避免硬编码,实现代码的组件化。反射的这些特点在对灵活性和扩展性要求很高的框架上有巨大的作用。 当然,也需要注意到,反射通过字符串进行操作的方式是解释性的,这将导致性能的降低。 二、反射的原理 对于拥有虚拟机(或者类似的东西,虚拟机只是一个不正规的名词)的语言,都存在加载字节码(同样不正规的名词)到虚拟机的过程。在这个过程中,虚拟机获取了有关类的信息,包括继承关系、包含的字段和方法等等。对于java来说,局部变量放在栈中,类实例放在堆中,程序方法放在方法区中。 对不使用反射的一般情况来说,方法调用更加直接。调用时虚拟机将根据编译时即确定的方法地址进行跳转。而对于反射,则需要根据字符串查找对应的类或方法。这样查找而非硬编码的过程就会影响性能。 二、java中的反射 通过反射我们能获取java语言中的如下组成部分:包、类(和接口)、方法(一般/构造)、字段、注解。反射不能操作方法中的内容。 类是面向对象的基本单元,我们通过获取类来实现对程序的动态操作。 (1)类和包 “类” Class<?> 是一个用于表示类的类型。它有三种获取方式 ClassName.class // 类型名.class obj.getClass(); // 对象.getClass Class.forName(String className); // Class.forName("包含包路径的类型全称") 前两种较好理解,相当于获取一个类型,我们可以用这编写一个类似于 instanceof 的函数。 boolean typeof(Object obj, Class<?> cls) { return obj.getClass() == cls; } 当然这无法将子类也判断为真。值得注意的是这里我们直接使用了 == 而不是 equals。因为对于每一个类,Class只用一个实例。 但第三种才最为重要,它通过字符串获取了一个类型。这就为程序提供了灵活性。 获取了一个 Class 对象后,我们可以进一步获取其父类和实现的接口 Class<?> cls = Class.forName("somepackages.someClass"); Class<?> superCls = cls.getSuperclass(); Class<?>[] interfaces = cls.getInterfaces(); 值得注意的是获取接口方法返回的是一个 Class 数组。这说明对于虚拟机来说本没有类和接口之分。 调用 getPackage 可以获取包 Package p = cls.getPackage(); Package 类型保存了该包的一些信息,如名称、版本等等,不一一列举。...