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

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


当前回答

重要的

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

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

请参阅了解Java 9模块

其他回答

反射有很多用途。我更熟悉的是能够动态创建代码。

IE:基于任何数据的动态类、函数、构造函数(xml/array/sql results/hardcoded/etc.)

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

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

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

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

正如名称本身所暗示的,它除了提供在运行时动态调用创建实例的方法的功能之外,还反映了它所持有的例如类方法等。

许多框架和应用程序都使用它来调用服务,而实际上并不知道代码。

并非每种语言都支持反射,但在支持反射的语言中,原则通常是相同的。

反思是对程序结构进行“反思”的能力。或者更具体。查看您拥有的对象和类,并以编程方式获取有关它们实现的方法、字段和接口的信息。您还可以查看注释之类的内容。

它在很多情况下都很有用。您希望能够在代码中动态插入类的任何地方。许多对象关系映射器使用反射来实例化数据库中的对象,而无需事先知道它们将使用什么对象。插件架构是反射有用的另一个地方。在这些情况下,能够动态加载代码并确定是否有类型实现了作为插件使用的正确接口非常重要。

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

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,但如果过度使用,它可能会降低应用程序的速度,因为它在运行时解析所有类型。