我只是好奇,为什么我们首先要使用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函数呢?
让一切变得动态?
答案 0 :(得分:33)
简单地说:因为有时你在编译时不知道“Foo”或“hello”部分。
你做的绝大多数时间知道这一点,所以不值得使用反射。然而,偶尔,你不会 - 而且在那时,你可以转向反思。
例如,protocol buffers允许您生成代码,其中包含用于读取和写入消息的完整静态类型代码,或者生成的代码足以使其余部分可以通过反射完成:在反射情况下,加载/保存代码必须通过反射获取和设置属性 - 它知道由于消息描述符而涉及的属性的名称。这种情况要慢很多,但却会产生相当少的代码。
另一个例子是依赖注入,其中用于依赖项的类型的名称通常在配置文件中提供:然后DI框架必须使用反射来构造所涉及的所有组件,沿着该框架查找构造函数和/或属性。方式。
答案 1 :(得分:5)
只要您(=您的方法/您的类)在编译时不知道 该类型应该实例化或应该调用它的方法,就会使用它。
此外,许多框架使用反射来分析和使用您的对象。例如:
String
,您可以获取目标类,获取具有已配置名称的方法,并在编译时不知道它的情况下调用它。答案 2 :(得分:3)
典型的用法是插件机制,它支持在编译时未知的类(通常是接口的实现)。
答案 3 :(得分:3)
您可以使用反射来自动执行任何可以有用地使用对象方法和/或属性列表的过程。如果你曾经花时间编写代码在每个对象的字段上执行大致相同的事情 - 保存和加载数据的明显方法通常就是这样 - 那么反射可以自动为你做的事情。 / p>
最常见的应用可能就是以下三种:
XmlSerializer
)答案 4 :(得分:2)
使用反射,您可以非常轻松地编写详细说明文本中方法/字段的配置,使用这些配置的框架可以读取字段的文本描述并找到真实的相应字段。
e.g。 JXPath允许您导航这样的对象:
//company[@name='Sun']/address
所以JXPath会查找方法getCompany()
(对应company
),这个字段名为name
等。
您可以在Java中的许多框架中找到它,例如JavaBeans,Spring等。
答案 5 :(得分:1)
它对序列化和对象关系映射等很有用。您可以编写一个泛型函数来使用反射来序列化对象,以获取对象的所有属性。在C ++中,您必须为每个类编写一个单独的函数。
答案 6 :(得分:1)
之前我曾在一些验证类中使用过它,在构造函数中传递了一个大型的复杂数据结构,然后运行了数百个(实际上是几百个)方法来检查数据的有效性。我的所有验证方法都是私有的并且返回了布尔值,所以我做了一个你可以调用的“验证”方法,它使用反射来调用类中的所有私有方法而不是返回的布尔值。
这使得验证方法更简洁(不需要枚举每个小方法)并且所有方法都被运行(例如,某人编写了新的验证规则并忘记在main方法中调用它)。
更改为使用反射后,我没有发现任何有意义的性能损失,代码更容易维护。
答案 7 :(得分:0)
除了Jons的答案之外,另一种用法是能够“将你的脚趾浸入水中”来测试JVM中是否存在给定的设施。
在OS X下,如果调用某些Apple提供的类,则java应用程序看起来更好。测试这些类是否存在的最简单方法是首先使用反射进行测试
答案 8 :(得分:0)
有时你需要在飞行中或从其他地方而不是java代码(例如jsp)创建类的对象。那时反思很有用。