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

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


当前回答

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

反射本身是指Java和C#等缺乏自我认知和自我感知能力的语言。因为他们没有自知之明的能力,当我们想要观察它的样子时,我们必须有另一件事来反思它的样子。优秀的动态语言,如Ruby和Python,可以在没有其他人帮助的情况下感知自己的反射。我们可以说,Java的对象在没有镜像的情况下无法感知它的样子,镜像是反射类的对象,但Python中的对象可以在没有镜像时感知它。这就是为什么我们需要在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,但如果过度使用,它可能会降低应用程序的速度,因为它在运行时解析所有类型。

反射是允许应用程序或框架处理可能尚未编写的代码的关键机制!

以典型的web.xml文件为例。这将包含一个servlet元素列表,其中包含嵌套的servlet类元素。servlet容器将处理web.xml文件,并通过反射创建每个servlet类的新实例。

另一个例子是Java API for XML Parsing(JAXP)。其中,XML解析器提供程序是通过众所周知的系统财产“插入”的,这些属性用于通过反射构造新实例。

最后,最全面的例子是Spring,它使用反射创建bean,并大量使用代理

反射使您能够编写更通用的代码。它允许您在运行时创建对象并在运行时调用其方法。因此,程序可以高度参数化。它还允许对对象和类进行内省,以检测其暴露于外部世界的变量和方法。

从java文档页面

java.lang.reflect包提供了用于获取关于类和对象的反射信息的类和接口。反射允许编程访问有关已加载类的字段、方法和构造函数的信息,以及在安全限制内使用反射字段、方法或构造函数对其底层对应对象进行操作。

如果必要的ReflectPermission可用,AccessibleObject允许禁止访问检查。

此包中的类与java.lang.Class一起容纳调试器、解释器、对象检查器、类浏览器等应用程序,以及需要访问目标对象的公共成员(基于其运行时类)或给定类声明的成员的服务(如object Serialization和JavaBeans)

它包括以下功能。

获取类对象,检查类(字段、方法、构造函数)的财产,设置和获取字段值,调用方法,创建对象的新实例。

查看Class类公开的方法的文档链接。

本文(由Sosnoski Software Solutions,Inc总裁Dennis Sosnosiki撰写)和本文(security-explorations pdf):

与使用反射相比,我可以看到相当多的缺点

反射用户:

它提供了动态链接程序组件的多种方式它对于创建以非常通用的方式处理对象的库非常有用

反射的缺点:

当用于字段和方法访问时,反射比直接代码慢得多。它可以隐藏代码中的实际情况它绕过源代码会产生维护问题反射代码也比相应的直接代码更复杂它允许违反关键Java安全约束,例如作为数据访问保护和类型安全

一般滥用:

加载限制类,获取对受限类的构造函数、方法或字段的引用,创建新的对象实例、方法调用、获取或设置受限类的字段值。

看看这个关于滥用反射功能的SE问题:

如何在Java中读取私有字段?

摘要:

在系统代码中不安全地使用其功能也很容易导致Java安全模型的破坏。因此,谨慎使用此功能

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

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