3

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

在版本 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() 是否安全,如果答案是“有时”或“取决于”,那么为什么在这种情况下不可行?

4

2 回答 2

1

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

于 2013-08-07T04:44:59.163 回答
0

您得到的错误是完全有效的。

选项 1:在您的代码中使用反射来动态地使用您在运行时找到的任何版本的库来做正确的事情。

选项 2:如果您希望您的代码与库的任一版本一起运行,您将需要在编译时两个版本都可用。您将需要一些代码来决定在运行时使用哪个版本,并有条件地执行编译后的代码以调用库的正确版本。如果库作者不友善,您最终可能不得不解决类名冲突。

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

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

于 2013-08-07T04:51:57.440 回答