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

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


当前回答

反射允许在运行时动态实例化新对象、调用方法和获取/设置类变量的操作,而无需事先了解其实现。

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");

在上面的示例中,null参数是要对其调用方法的对象。如果方法是静态的,则提供null。如果该方法不是静态的,那么在调用时需要提供有效的MyObject实例而不是null。

反射还允许您访问类的私有成员/方法:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}

.

A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);

为了检查类(也称为内省),不需要导入反射包(java.lang.reflect)。可以通过java.lang.Class访问类元数据。

反射是一个非常强大的API,但如果过度使用,它可能会降低应用程序的速度,因为它在运行时解析所有类型。

其他回答

重要的

从Java9开始,您不能再使用反射,除非package-info.Java打开模块以进行反射访问。

默认情况下,拒绝对模块中的所有包进行“反射”访问。

请参阅了解Java 9模块

反射是让物体看到它们的外观。这个论点似乎与反思无关。事实上,这就是“自我识别”能力。

反射本身是指Java和C#等缺乏自我认知和自我感知能力的语言。因为他们没有自知之明的能力,当我们想要观察它的样子时,我们必须有另一件事来反思它的样子。优秀的动态语言,如Ruby和Python,可以在没有其他人帮助的情况下感知自己的反射。我们可以说,Java的对象在没有镜像的情况下无法感知它的样子,镜像是反射类的对象,但Python中的对象可以在没有镜像时感知它。这就是为什么我们需要在Java中进行反射。

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

例如,Java中的所有对象都有getClass()方法,该方法允许您确定对象的类,即使您在编译时不知道它(例如,如果您将其声明为object)-这可能看起来微不足道,但这种反射在动态性较差的语言(如C++)中是不可能的。更高级的用法允许您列出和调用方法、构造函数等。

反射是很重要的,因为它让你编写的程序不必在编译时“知道”一切,使它们更加动态,因为它们可以在运行时绑定在一起。代码可以针对已知的接口编写,但要使用的实际类可以使用配置文件的反射来实例化。

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

反射是一组函数,允许您访问程序的运行时信息并修改其行为(有一些限制)。

它很有用,因为它允许您根据程序的元信息更改运行时行为,也就是说,您可以检查函数的返回类型并更改处理情况的方式。

例如,在C#中,您可以在运行时加载程序集(.dll)并检查它,浏览类并根据找到的内容执行操作。它还允许您在运行时创建类的实例,调用其方法等。

它在哪里有用?不是每次都有用,而是针对具体情况。例如,您可以使用它获取用于日志记录的类名称,根据配置文件中指定的内容动态创建事件处理程序,等等。。。

我最喜欢的反射用法之一是下面的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();
}