什么是反思,为什么它有用?

什么是反思,为什么它有用?

我对Java特别感兴趣,但我认为任何语言的原则都是一样的。


反射名称用于描述能够检查同一系统(或其本身)中的其他代码的代码。

例如,假设你在Java中有一个未知类型的对象,并且你想在它上面调用一个'doSomething'方法。 除非对象符合已知接口,否则Java的静态类型系统并不是真正用于支持它的,但是使用反射,代码可以查看对象并查看它是否具有名为“doSomething”的方法,然后在您调用它时调用它想要。

所以,给你一个在Java中的代码示例(假设所讨论的对象是foo):

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

Java中一个非常常见的用例是带注释的用法。 例如,JUnit 4将使用反射来查看您的类,以查看使用@Test注释标记的方法,然后在运行单元测试时调用它们。

http://docs.oracle.com/javase/tutorial/reflect/index.html有一些很好的反思示例。

最后,是的,这些概念在其他支持反射的静态类型语言(如C#)中非常相似。 在动态类型语言中,上述用例不太必要(因为编译器将允许任何方法在任何对象上被调用,如果不存在则在运行时失败),但第二种情况是寻找标记或以某种方式工作仍然很普遍。

重要的评论更新:

检查系统中的代码并查看对象类型的能力不是反射,而是类型自相关。 那么反思就是通过利用内省在运行时进行修改的能力。 这里的区别是必要的,因为有些语言支持反思,但不支持反思。 一个这样的例子是C ++


反射是一种语言在运行时检查和动态调用类,方法,属性等的能力。

例如,Java中的所有对象都有getClass()方法,即使您在编译时不知道对象的类,也可以确定对象的类(例如,如果将其声明为Object ) - 这可能看起来很平凡,但这样反射在C++等动态较差的语言中是不可能的。 更高级的用途可以让你列出和调用方法,构造函数等。

反射非常重要,因为它可以让您编写不需要在编译时“知道”所有内容的程序,使它们更具动态性,因为它们可以在运行时绑定在一起。 代码可以用已知的接口编写,但实际使用的类可以使用配置文件中的反射来实例化。

出于这个原因,许多现代框架广泛使用反射。 大多数其他现代语言也使用反射,而在脚本语言(如Python)中,它们甚至更紧密地集成在一起,因为在这些语言的通用编程模型中感觉更自然。


我最喜欢使用的反射之一是下面的Java转储方法。 它将任何对象作为参数,并使用Java反射API打印出每个字段的名称和值。

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
    callCount++;
    StringBuffer tabs = new StringBuffer();
    for (int k = 0; k < callCount; k++) {
        tabs.append("t");
    }
    StringBuffer buffer = new StringBuffer();
    Class oClass = o.getClass();
    if (oClass.isArray()) {
        buffer.append("n");
        buffer.append(tabs.toString());
        buffer.append("[");
        for (int i = 0; i < Array.getLength(o); i++) {
            if (i < 0)
                buffer.append(",");
            Object value = Array.get(o, i);
            if (value.getClass().isPrimitive() ||
                    value.getClass() == java.lang.Long.class ||
                    value.getClass() == java.lang.String.class ||
                    value.getClass() == java.lang.Integer.class ||
                    value.getClass() == java.lang.Boolean.class
                    ) {
                buffer.append(value);
            } else {
                buffer.append(dump(value, callCount));
            }
        }
        buffer.append(tabs.toString());
        buffer.append("]n");
    } else {
        buffer.append("n");
        buffer.append(tabs.toString());
        buffer.append("{n");
        while (oClass != null) {
            Field[] fields = oClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                buffer.append(tabs.toString());
                fields[i].setAccessible(true);
                buffer.append(fields[i].getName());
                buffer.append("=");
                try {
                    Object value = fields[i].get(o);
                    if (value != null) {
                        if (value.getClass().isPrimitive() ||
                                value.getClass() == java.lang.Long.class ||
                                value.getClass() == java.lang.String.class ||
                                value.getClass() == java.lang.Integer.class ||
                                value.getClass() == java.lang.Boolean.class
                                ) {
                            buffer.append(value);
                        } else {
                            buffer.append(dump(value, callCount));
                        }
                    }
                } catch (IllegalAccessException e) {
                    buffer.append(e.getMessage());
                }
                buffer.append("n");
            }
            oClass = oClass.getSuperclass();
        }
        buffer.append(tabs.toString());
        buffer.append("}n");
    }
    return buffer.toString();
}
链接地址: http://www.djcxy.com/p/1291.html

上一篇: What is reflection and why is it useful?

下一篇: Can anyone explain what JSONP is, in layman terms?