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

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


当前回答

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

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

其他回答

例子:

以一个远程应用程序为例,它为您的应用程序提供了一个对象,您可以使用其API方法获取该对象。现在,基于对象,您可能需要执行某种计算。

提供者保证对象可以是3种类型,我们需要根据对象的类型进行计算。

因此,我们可以在3个类中实现,每个类包含不同的逻辑。显然,对象信息在运行时可用,因此您无法静态编码以执行计算,因此反射用于实例化类的对象,您需要根据从提供程序接收的对象执行计算。

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

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

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

我想举个例子来回答这个问题。首先,Hibernate项目使用反射API生成CRUD语句,以弥合运行应用程序和持久性存储之间的鸿沟。当域中的情况发生变化时,Hibernate必须了解这些情况,才能将其持久化到数据存储中,反之亦然。

另外,Lombok项目也可以。它只是在编译时注入代码,导致代码被插入到域类中。(我认为这对getter和setter来说是可以的)

Hibernate选择反射是因为它对应用程序的构建过程影响最小。

在Java7中,我们有MethodHandles,它用作反射API。在项目中,要使用记录器,我们只需复制粘贴下一个代码:

Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

因为在这种情况下很难出错。

从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安全模型的破坏。因此,谨慎使用此功能

反射是一种API,用于在运行时检查或修改方法、类和接口的行为。

反射所需的类在java.lang.reflect包中提供。反射为我们提供了有关对象所属的类的信息,以及可以使用该对象执行的该类的方法。通过反射,我们可以在运行时调用方法,而不考虑与它们一起使用的访问说明符。

java.lang和java.lang.reflect包为java反射提供了类。

反射可用于获取以下信息:

类getClass()方法用于获取对象所属类的名称。构造函数getConstructors()方法用于获取对象所属类的公共构造函数。方法getMethods()方法用于获取对象所属类的公共方法。

反射API主要用于:

IDE(集成开发环境),例如Eclipse、MyEclipse、NetBeans等。调试器和测试工具等。

使用反射的优点:

可扩展性特性:应用程序可以通过使用扩展性对象的完全限定名称创建扩展性对象实例来使用外部用户定义的类。

调试和测试工具:调试器使用反射属性来检查类上的私有成员。

缺点:

性能开销:反射操作的性能低于非反射操作,应避免在性能敏感应用程序中频繁调用的代码段中使用。

内部暴露:反射代码打破了抽象,因此可能会随着平台的升级而改变行为。

参考:Java Reflection javareviewed.blogspot.in