Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop Java/C等中反射的用途是什么_Oop_Reflection_Theory - Fatal编程技术网

Oop Java/C等中反射的用途是什么

Oop Java/C等中反射的用途是什么,oop,reflection,theory,Oop,Reflection,Theory,我只是好奇,为什么我们首先要使用 // 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); 我们可以简单地创建一个对象并调用类的

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

// 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和GetmHod函数来实现同样的操作呢


要使一切都动态?

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

绝大多数时候你都知道这一点,所以不值得使用反射。然而,只是偶尔,你不会——在这一点上,你只能求助于反射

例如,允许您生成包含完整静态类型代码用于读写消息的代码,或者生成足够的代码,以便通过反射完成其余工作:在反射情况下,加载/保存代码必须通过反射获取和设置属性——由于消息描述符,它知道所涉及的属性的名称。这要慢得多,但生成的代码要少得多


另一个例子是依赖项注入,其中用于依赖项的类型的名称通常在配置文件中提供:然后DI框架必须使用反射来构造所有涉及的组件,同时查找构造函数和/或属性。

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

除了Jons answer之外,另一个用法是能够“浸入水中”来测试JVM中是否存在给定的功能


在OSX下,如果调用一些苹果提供的类,java应用程序看起来会更好。测试这些类是否存在的最简单方法是首先使用反射进行测试,这对于序列化和对象关系映射之类的事情很有用。您可以编写一个泛型函数,通过使用反射获取对象的所有属性来序列化对象。在C++中,你必须为每个类编写一个单独的函数。

< P>你可以使用反射来自动化任何有用的对象的方法和/或属性列表。如果您曾经花时间编写代码,在对象的每个字段上依次执行大致相同的操作—保存和加载数据的明显方式通常是这样的—那么反射可以自动为您执行这项操作

最常见的应用可能有以下三种:

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

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

e、 g.JXPath允许您导航如下对象:

//company[@name='Sun']/address
因此,JXPath将查找一个方法
getCompany()
(对应于
company
),该方法中的一个字段称为
name

在Java的许多框架中都会发现这一点,例如JavaBeans、Spring等。

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

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

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

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

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


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

有时您需要动态创建类对象,或者从其他地方创建非java代码(例如jsp)的对象。那时,反射是有用的。

@Jon:这不是重复的吗?@John:可能是。老实说,我很难找到重复的。