|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
编程范型（按语言比较（英语：）） |
| --- |
|  |
| 指令式 | 
* 过程式
* 块结构
* 例外处理
* 结构化
* 模块化

 |
|  |
| 函数式 | 
* 头等函数
* 纯函数式
* 隐式
* 模式匹配
* 推导式

 |
|  |
| 面向对象 | 
* 基于类
* 基于原型
* 契约式
* 面向方面
* 面向代理

 |
|  |
| 数据流程 | 
* 同步式
* 响应式
	+ 函数式响应式
* 串流处理
* 基于流程

 |
|  |
| 宣告式 | 
* 逻辑式
	+ 回答集
* 约束式
* 数据查询
* 框架本体

 |
|  |
|  | 
* 协程
* 演员模型
* 通信顺序进程
* future/promise
* 分叉会合
* 整体同步
* 映射归约

 |
|  |
| 其他 | 
* 递归
* 阵列式
* 多态
	+ 运算符重载
	+ 泛型
	+ 多分派
* 面向堆栈
* 非确定性
* 数据驱动
* 事件驱动
* 自动机
* 可微分
* 概率式

 |

 |

在计算机学中，**反射式编程**（英語：）或**反射**（英語：），是指计算机程序在运行时（）可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说，反射就是程序在运行的时候能够"观察"并且修改自己的行为。

要注意术语"反射"和"内省"（）的关系。内省（或称"自省"）机制仅指程序在运行时对自身信息（称为元数据）的检测；反射机制不仅包括要能在运行时对程序自身信息进行检测，还要求程序能进一步根据这些信息改变程序状态或结构。

概况
--

反射用于观察并修改程序在运行时的行为。一个反射導向的程式组件可以监测一个范围内的代码执行情况，可以根据获取的目标对象信息及与此相关的范围修改自身。这可通过在运行时动态分配程序代码实现。

在类型检测严格的面向对象的编程语言如Java中，一般需要在编译期间对程序中需要调用的对象的具体类型、介面（interface）、資料成員（fields）和方法的合法性进行检查。反射技术则允许将对需要调用的物件的訊息检查工作从编译期间推迟到运行期间再现场执行。这样一来，可以在编译期间先不明确目标物件的介面（interface）名称、字段（fields），即物件的資料成員（成员变量）、可用方法，然后在运行根据目标物件自身的訊息决定如何处理。它还允许根据判断结果进行实例化新物件和相关方法的呼叫。

反射主要用途就是使给定的程式，动态地适应不同的运行情况。利用物件導向建模中的多型（多态性）也可以简化编写分别适用于多种不同情形的功能代码，但是反射可以解决多型（多态性）并不适用的更普遍情形，从而更大程度地避免硬编码（即把代码的细节"写死"，缺乏灵活性）的代码风格。

反射也是元编程的一个关键策略。

历史背景
----

早期计算机的原生汇编语言本质上就具有反射特性。因为这些最初架构可以通过定义指令作为数据及使用自修改代码来编程，实现反射功能是很平常的。编程发展到使用编译型高级语言如Algol、Cobol、Fortran和包括Pascal和C在内的很多其他语言时，自修改代码等实践很大程度上消失了，直到将反射特性内建入类型系统的高级编程语言出现后才再次提供了反射功能。Lisp语言家族以具有同像性作为标志性特征，可以认为具有反射性。

1982年，布莱恩·史密斯（英语：）在其博士论文《编程语言中的过程式反射》中，向过程式编程语言介入了"计算反射"的概念，并且引入自循環直譯器概念用作3-Lisp的一个组成部份。

特点
--

### 优点

支持反射的语言提供了一些在早期高级语言中难以实现的运行时特性。

* 可以在一定程度上避免硬编码，提供灵活性和通用性。
* 可以作为一个頭等物件发现并修改源代码的结构（如代码块、类、方法、协议等）。
* 可以在运行时像对待源代码语句一样动态解析字符串中可执行的代码（类似JavaScript的eval()函数），进而可将跟class或function匹配的字符串转换成class或function的调用或引用。
* 可以创建一个新的语言字节码解释器来给编程结构一个新的意义或用途。

### 劣势

* 此技术的学习成本高。面向反射的编程需要较多的高级知识，包括框架、关系映射和对象交互，以实现更通用的代码执行。
* 同样因为反射的概念和语法都比较抽象，过多地滥用反射技术会使得代码难以被其他人读懂，不利于合作与交流。
* 由于将部分信息检查工作从编译期推迟到了运行期，此举在提高了代码灵活性的同时，牺牲了一点点运行效率。

通过深入学习反射的特性和技巧，它的劣势可以尽量避免，但这需要许多时间和经验的积累。

例子
--

下列代码片段建立类Foo的一个实例foo，并调用它的方法PrintHello。对于每个编程语言，展示平常的和基于反射的调用序列。

### C#

```
// Without reflection
Foo foo = new Foo();
foo.PrintHello();

// With reflection
Object foo = Activator.CreateInstance("complete.classpath.and.Foo");
MethodInfo method = foo.GetType().GetMethod("PrintHello");
method.Invoke(foo, null);

```

### Go

```
import "reflect"

// Without reflection
f := Foo{}
f.Hello()

// With reflection
fT := reflect.TypeOf(Foo{})
fV := reflect.New(fT)

m := fV.MethodByName("Hello")
if m.IsValid() {
 m.Call(nil)
}

```

### Java

```
import java.lang.reflect.Method;

// Without reflection
Foo foo = new Foo();
foo.hello();

// With reflection
try {
 // Alternatively: Object foo = Foo.class.newInstance();
 Object foo = Class.forName("complete.classpath.and.Foo").newInstance();

 Method m = foo.getClass().getDeclaredMethod("hello", new Class<?>[0]);
 m.invoke(foo);
} catch (Exception e) {
 // Catching ClassNotFoundException, NoSuchMethodException
 // InstantiationException, IllegalAccessException
}

```

### Perl

```
# Without reflection
my $foo = Foo->new;
$foo->hello;

# or
Foo->new->hello;

# With reflection
my $class = "Foo"
my $constructor = "new";
my $method = "hello";

my $f = $class->$constructor;
$f->$method;

# or
$class->$constructor->$method;

# with eval
eval "new Foo->hello;";

```

### PHP

```
// Without reflection
$foo = new Foo();
$foo->hello();

// With reflection, using Reflections API
$reflector = new ReflectionClass('Foo');
$foo = $reflector->newInstance();
$hello = $reflector->getMethod('hello');
$hello->invoke($foo);

```

### Python

```
# Without reflection
obj = Foo()
obj.hello()

# With reflection
obj = globals()['Foo']() # globals() Return a dictionary representing the current global symbol table. 
getattr(obj, 'hello')()  # getattr(object, name) Return the value of the named attribute of object. 

# With eval
eval('Foo().hello()')

```

### R

```
# Without reflection, assuming foo() returns an S3-type object that has method "hello"
obj <- foo()
hello(obj)

# With reflection
the.class <- "foo"
the.method <- "hello"
obj <- do.call(the.class, list())
do.call(the.method, alist(obj))

```

### Ruby

```
# Without reflection
obj = Foo.new
obj.hello

# With reflection
class\_name = "Foo"
method\_name = :hello
obj = Object.const\_get(class\_name).new
obj.send method\_name

# With eval
eval "Foo.new.hello"

```

常见应用
----

* 反射经常作为软件测试的一部分，比如运行时创建/实例化模拟对象。
* Java语言解析XML文件的技术用到了反射。

参见
--

* 程序自修改
* 反射式编程语言和平台列表

参考资料
----

### 引用

1. 1 2  见Forman 2005，第8頁。
2. ↑  Brian Cantwell Smith, Procedural Reflection in Programming Languages, Department of Electrical Engineering and Computer Science, Massachusetts Institute of Technology, PhD dissertation, 1982.
3. ↑ .  [2023-01-26]. （原始内容存档于2023-01-26）.
4. 1 2 3 4  见Forman 2005，第4頁。

### 来源

* Ira R. Forman, Nate Forman.  [Java反射实战] 1. Manning Publications Co. 2005年. ISBN 1-932394-18-4 （英语）.  使用`|accessdate=`需要含有`|url=` (帮助)

外部链接
----

* Reflection in logic, functional and object-oriented programming: a short comparative study （页面存档备份，存于）
* An Introduction to Reflection-Oriented Programming
* Brian Foote's pages on Reflection in Smalltalk （页面存档备份，存于）
* Java Reflection API Tutorial （页面存档备份，存于） from Oracle

|  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
编程语言类别（維基數據所列：） |
| --- |
|  |
| 范型 | 
* 指令式
* 过程式
* 函数式
* 逻辑式
* 基于类
* 面向对象
* 基于原型
* 基于对象
* 面向方面
* 数据流程
* 同步式
* 动态
* 脚本
* 元编程
* 宏
* 反射式
* 事件驱动
* 并发
* 基于演员
* 管道
* 阵列
* 串接
* 面向堆栈
* 宣告式
* 模板
* 可扩展（英语：）
* 基于规则
* 领域特定
* 多重范型
* 触控（英语：）

 |
|  |
| 编程语言层次 | 
* 机器
* 汇编
* 编译
* 解释
* 低级
* 高级
* 极高级

 |
|  |
| 有关 | 
* 世代
* 非英语基础（英语：）
* 可视化

 |

 |