搜索和调用反射方法的开销

时间:2009-04-27 13:49:33

标签: java reflection

我有一个应该读取消息的类,从信封中提取其类型,然后调用必须处理消息的方法;在每个消息类型与枚举成员相关联。

有30多种消息类型。

发送消息的一种方法是只使用一个开关,但它真的很丑陋且容易出错(我已经知道了这种情况吗?我有两次这种情况吗?)。

另一种方法是使用单个方法进程(数据)定义接口,并为实现该接口的每种消息类型创建一个类,使用映射注册这些类,并且在应该处理消息的代码中, call map.get(messageType).process(data);但是创建30多个课程真的很烦人。

另一种方法是使用反射:为每个消息类型定义一个函数,具有精确的签名和模式名称,如processMessagetype;然后创建一个从messagetype到Method的地图(在getDeckaredMethods()上填充一个简单的搜索)然后执行以下操作: map.get(为messageType).invoke(这一点,数据)。

你应该使用什么方法?使用java的反射有什么开销?

5 个答案:

答案 0 :(得分:4)

如果你正在寻找好的表现,那么反思会有很大的开销。如果您的例程(消息调度)将被一遍又一遍地使用,那么替代方案会更好。此外,如果从OO的角度来看,IMO会更好,因为正如Brian所述,他的答案更容易,也更便宜。

处理30多条消息的clas可以很容易地增加到100多条消息,然后你将拥有一个包含100多种方法的类,添加私有方法,代码重用将很难,你的类刚刚变得一团糟。

反射多态和切换的开销是这样的:

time spent on a switch case call: 1
time spent on a polymorphism call: 1.1
time spent on a reflection call: 1.9-2.0

我不久前对这些人进行了基准测试,这些都是我的结果,我现在没有代码,因为这些基准测试是在我以前的公司完成的,而且我再也无法访问该代码了。

答案 1 :(得分:2)

您可以将处理方法添加到枚举。

一个大开关究竟出了什么问题(每个案例只调用一个方法)?

反思的主要代价是它往往会让代码变得糟透了。 ;)

答案 2 :(得分:1)

你没有说你的process()方法会做什么,但如果调度方法调用的任何开销都很重要,我会感到惊讶。

我会让语言和OO系统为您工作,并使用适当的方法实现创建一个接口/抽象基类。

请记住,过早优化是万恶之源(Knuth

答案 3 :(得分:1)

我会猜测,因为你正在谈论“消息”和“信封”,你正在通过网络传递这些消息。这样做的时间绝对支配反射所需的额外时间。我已经使用了这样的反射,这不是一个糟糕的模型。

答案 4 :(得分:0)

我认为您描述的第一个方法/算法(消息类型映射到类)将随着时间的推移更容易管理更新,维护等。

你描述的第二种模式基本上涉及一个包含大约30多种方法的类,对吗?随着时间的推移管理会非常痛苦。

每种消息类型都需要真正独特的处理逻辑吗?通过创建用于处理消息的接口的实现,您可能可以从类型层次结构中受益,即可以处理解析特定系列消息的超类,然后您只需在该族的消息不同的区域中覆盖它。 ..