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

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


当前回答

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

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

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

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

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

反射API主要用于:

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

使用反射的优点:

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

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

缺点:

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

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

参考:Java Reflection javareviewed.blogspot.in

其他回答

反射的简单示例。在国际象棋游戏中,您不知道用户在运行时会移动什么。反射可用于调用已在运行时实现的方法:

public class Test {

    public void firstMoveChoice(){
        System.out.println("First Move");
    } 
    public void secondMOveChoice(){
        System.out.println("Second Move");
    }
    public void thirdMoveChoice(){
        System.out.println("Third Move");
    }

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
        Test test = new Test();
        Method[] method = test.getClass().getMethods();
        //firstMoveChoice
        method[0].invoke(test, null);
        //secondMoveChoice
        method[1].invoke(test, null);
        //thirdMoveChoice
        method[2].invoke(test, null);
    }

}

反射的使用

反射通常由需要检查或修改在Java虚拟机中运行的应用程序的运行时行为的程序使用。这是一个相对高级的特性,只有对语言基础有很强理解的开发人员才能使用。考虑到这一点,反射是一种强大的技术,可以使应用程序执行不可能执行的操作。

可扩展性功能

应用程序可以通过使用扩展性对象的完全限定名称创建扩展性对象实例来使用外部用户定义的类。类浏览器和可视化开发环境类浏览器需要能够枚举类的成员。可视化开发环境可以受益于利用反射中可用的类型信息来帮助开发人员编写正确的代码。调试器和测试工具调试器需要能够检查类中的私有成员。测试工具可以利用反射来系统地调用类上定义的可发现集合API,以确保测试套件中的代码覆盖率较高。

反射的缺点

反射是强大的,但不应滥用。如果可以在不使用反射的情况下执行一个操作,那么最好避免使用它。

性能开销

由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。因此,反射操作的性能比非反射操作慢,应该避免在性能敏感应用程序中频繁调用的代码段中使用。

安全性限制

反射需要在安全管理器下运行时可能不存在的运行时权限。对于必须在受限安全上下文(如Applet)中运行的代码,这是一个重要的考虑因素。

内部构件暴露

由于反射允许代码执行在非反射代码中非法的操作,例如访问私有字段和方法,因此使用反射可能会导致意外的副作用,这可能会导致代码功能失调,并可能破坏可移植性。反射代码打破了抽象,因此可能会随着平台的升级而改变行为。

来源:反射API

我觉得最好用例子来解释,但没有一个答案能做到这一点。。。

使用反射的一个实际例子是用Java编写的Java语言服务器或用PHP编写的PHP语言服务器等。语言服务器为您的IDE提供自动完成、跳转到定义、上下文帮助、提示类型等功能。为了让所有标记名(可以自动完成的单词)在键入时显示所有可能的匹配项,语言服务器必须检查类的所有内容,包括文档块和私有成员。为此,它需要对所述阶级的反思。

另一个例子是私有方法的单元测试。这样做的一种方法是创建一个反射,并在测试的设置阶段将方法的范围更改为公开。当然,有人会认为不应该直接测试私有方法,但这不是重点。

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

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

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

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

例子:

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

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

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