维基百科文章 http://en.wikipedia.org/wiki/Type_introspection有一个相当不错的总结:
在计算中,类型自省是程序在运行时检查对象的类型或属性的能力。一些编程语言具有这种能力。
内省不应与反射混淆,后者更进一步,是程序在运行时操作对象的值、元数据、属性和/或函数的能力。一些编程语言,例如Java也具备这种能力。
采用静态类型的编译程序:
SomeType function foo(int i) {
return new SomeType(i);
}
所有类型都是已知的并在编译时强制执行,如果程序不满足其自己的显式类型约束,则甚至不应该编译。动态编程语言通常不会表现出这种严格性,变量的类型在编译时不一定是已知的。它们可能看起来更像这样:
function foo(i) {
return new SomeType(i);
}
该函数不能保证什么i
没错,只是穿越而已。这可能会或可能不会在某个地方引起问题,类型系统在这里无能为力。这种错误检查通常被归咎于用户态代码,因此此类代码需要自省功能:
function foo(i) {
if (!is_int(i)) {
throw new InvalidArgumentException;
}
return new SomeType(i);
}
内省和反思之间到底在哪里划清界线有些争议。人们可能会说内省是任何允许代码test某物是什么(“我是什么?”),而反射是操纵程序结构本身的能力。例如,一个 PHP 示例:
$ref = new ReflectionClass('Foo');
$foo = $ref->newInstanceWithoutConstructor();
上面的代码绕过了类的构造函数的运行Foo
创建它的新实例时。这就是运行时的代码操作。但实际上,PHP 中的反射 API 还包含自省功能。其中一些功能与“较低”内省功能的功能重复。例如。:
$ref = new ReflectionClass($obj);
if ($ref->getName() == 'Foo') ...
if ($obj instanceof Foo) ...
两个片段本质上都做同样的事情,但一个使用反射,另一个使用所谓的内省。正如您所看到的,几乎没有明确的分界线。然而,反思通常比内省更有力量。例如,在 PHP 中,您必须使用反射 API 来获取有关函数接受的参数类型的信息。这只是“被动”内省,但属于反射 API。但这主要是一个实际实施的问题。
简而言之,根据一般定义,要进行内省,程序需要能够在运行时检查自身的各个部分,并根据此信息执行不同的代码。除此之外,反射程序可以在运行时更改其自己的代码执行规则,例如选择不调用构造函数,否则这是语言定义的强制操作。