【问题标题】:What is the use of reflection in Java/C# etc [duplicate]Java / C#等中反射的用途是什么[重复]
【发布时间】:2011-01-30 02:51:56
【问题描述】:

我只是好奇,为什么我们首先要使用reflection

// Without reflection
Foo foo = new Foo();
foo.hello();

// With reflection
Class cls = Class.forName("Foo");
Object foo = cls.newInstance();
Method method = cls.getMethod("hello", null);
method.invoke(foo, null);

我们可以简单地创建一个对象并调用类的方法,但为什么使用 forName、newInstance 和 getMthod 函数也一样呢?

让一切都充满活力?

【问题讨论】:

    标签: oop reflection theory


    【解决方案1】:

    简单地说:因为有时您在编译时不知道“Foo”或“hello”部分。

    绝大多数时间你确实知道这一点,因此不值得使用反射。然而,只是偶尔,你不会——在那个时候,你可以求助于反思。

    例如,protocol buffers 允许您生成包含用于读取和写入消息的完整静态类型代码的代码,或者生成的代码刚好足以让其余部分可以通过反射完成:在反射情况下,加载/保存代码必须通过反射获取和设置属性 - 由于消息描述符,它知道所涉及的属性的名称。这会慢很多(很多),但生成的代码要少得多。

    另一个例子是依赖注入,其中用于依赖的类型的名称通常在配置文件中提供:DI 框架然后必须使用反射来构造所有涉及的组件,沿着方式。

    【讨论】:

    • @Jon:这不是重复的吗?
    • @John:可能。老实说,我在查找重复项方面很薄弱。
    【解决方案2】:

    当您(=您的方法/您的类)在编译时不知道该类型应该实例化或它应该调用的方法时使用它。

    此外,许多框架使用反射来分析和使用您的对象。例如:

    • hibernate/nhibernate(以及任何对象关系映射器)使用反射来检查类的所有属性,以便在执行数据库操作时能够更新或使用它们
    • 您可能希望可以配置应用程序默认执行用户定义类的哪个方法。配置的值为String,可以获取目标类,获取配置名称的方法,调用它,编译时不知道。
    • 解析注解是通过反射完成的

    【讨论】:

      【解决方案3】:

      典型的用法是插件机制,它支持编译时未知的类(通常是接口的实现)。

      【讨论】:

        【解决方案4】:

        您可以使用反射来自动化任何可以有用地使用对象的方法和/或属性列表的过程。如果您曾经花时间编写代码,轮流在对象的每个字段上执行大致相同的操作——保存和加载数据的明显方式通常是这样工作的——那么反射可以自动为您做一些事情。

        最常见的应用大概是这三个:

        • 序列化(参见,例如,.NET 的 XmlSerializer
        • 生成用于编辑对象属性的小部件(例如,Xcode 的 Interface Builder、.NET 的对话框设计器)
        • 通过检查构造函数的类并在创建时提供合适的对象(例如,任何依赖注入框架)来创建具有任意依赖关系的对象的工厂

        【讨论】:

          【解决方案5】:

          使用反射,您可以非常轻松地编写详细描述方法/字段的文本配置,使用这些配置的框架可以读取字段的文本描述并找到真正对应的字段。

          例如JXPath 允许您像这样导航对象:

          //company[@name='Sun']/address
          

          所以 JXPath 将寻找一个方法 getCompany()(对应于 company),一个名为 name 等的字段。

          您会在 Java 的许多框架中找到这一点,例如JavaBeans、Spring 等。

          【讨论】:

            【解决方案6】:

            它对于序列化和对象关系映射之类的东西很有用。您可以编写一个通用函数来序列化对象,方法是使用反射来获取对象的所有属性。在 C++ 中,您必须为每个类编写一个单独的函数。

            【讨论】:

              【解决方案7】:

              我之前在一些验证类中使用过它,我在构造函数中传递了一个大而复杂的数据结构,然后运行了无数(实际上是几百个)方法来检查数据的有效性。我所有的验证方法都是私有的并返回布尔值,因此我创建了一个您可以调用的“验证”方法,它使用反射来调用类中的所有私有方法,而不是返回的布尔值。

              这使得 validate 方法更加简洁(不需要枚举每个小方法)并保证所有方法都在运行(例如,有人编写了新的验证规则并忘记在 main 方法中调用它)。

              改用反射后,我没有注意到任何有意义的性能损失,而且代码更易于维护。

              【讨论】:

                【解决方案8】:

                除了 Jons 的回答之外,另一种用法是能够“将脚趾浸入水中”以测试 JVM 中是否存在给定的设施。

                在 OS X 下,如果调用一些 Apple 提供的类,Java 应用程序看起来会更好。测试这些类是否存在的最简单方法是首先使用反射进行测试

                【讨论】:

                  【解决方案9】:

                  有时您需要在运行中或从其他地方创建类对象,而不是 java 代码(例如 jsp)。那个时候反思是有用的。

                  【讨论】:

                    猜你喜欢
                    • 2012-04-06
                    • 2011-02-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-03-10
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-04-07
                    相关资源
                    最近更新 更多