避免NoSuchMethodError需要反思?

时间:2013-08-07 04:34:43

标签: java reflection java-api

我正在针对图书馆进行编程。

在版本1中,该库有一个方法getFoo(),它返回一个Map

在版本2中,该方法getFoo()现在返回一个Set

我认为我的代码很开心:

  Object foo = library.getFoo();

并确定库是否返回Map或Set。

但是,当我针对库的版本1编译我的代码,但是针对版本2运行它时,我得到java.lang.NoSuchMethodError:getFoo()Ljava / util / Map;

至少这是

所发生的事情
java version "1.7.0_21"
OpenJDK Runtime Environment (IcedTea 2.3.9) (7u21-2.3.9-0ubuntu0.12.04.1)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

我现在通过使用反射来解决这个问题,但我认为没有必要。

所以我的问题是,执行Object foo = library.getFoo()是否安全,如果答案是“有时”或“它取决于”,那么为什么在这种情况下它没有问题呢?

2 个答案:

答案 0 :(得分:1)

使用版本1编译代码时,类字节代码具有此方法的条目,返回类型为Map。在运行时加载类,类定义的getFoo()返回类型为Map,因此JVM无法定位该方法,因为您针对具有不同返回类型的方法的类的不同版本运行它(Set在你的情况下)。

答案 1 :(得分:0)

您获得的错误完全有效。

选项1:在代码中使用反射,使用您在运行时找到的任何版本的库动态地执行正确的操作。

选项2:如果您希望代码与任一版本的库一起运行,则需要在编译时提供这两个版本。您将需要一些代码来确定在运行时使用的版本,并有条件地执行编译为调用适当版本库的代码。如果图书馆作者不友好,您可能最终不得不解决类名冲突。

反思(选项1)可能是最简单,最灵活的方法。

您可能想要创建一个包装器API来抽象两个版本的库之间的差异,因此这种ickiness不会泄漏到您的应用程序的其余部分。