27

我越来越:

NoSuchMethodError: com.foo.SomeService.doSmth()Z

我是否正确理解这'Z'意味着 doSmth() 方法的返回类型是布尔值?如果为真,那么这种方法确实不存在,因为这种方法返回了一些 Collection。但另一方面,如果我调用此方法,我不会将其返回值分配给任何变量。我只是这样称呼这个方法:

service.doSmth();

任何想法为什么会发生此错误?所有必要的 JAR 文件都存在,并且该类的所有其他方法似乎都存在。

4

7 回答 7

25

看起来方法在编译期间存在于类路径中,但在应用程序运行期间不存在。

我不认为返回类型是一个问题。如果是,它不会编译。当方法调用不明确时,编译器会抛出错误,这是当两个方法仅在返回类型上有所不同时。

于 2010-09-12T15:27:50.643 回答
18

通常,这个错误会被编译器捕获;如果类的定义发生了不兼容的更改,则此错误只会在运行时发生。

简而言之 - 运行时的类/jar 文件与您在编译时使用的不同。

于 2010-09-12T15:23:09.737 回答
17

这可能是您的编译时类路径和运行时类路径之间的差异。

以下是似乎正在发生的事情:

  • doSmth()代码使用定义返回布尔值的方法的类路径编译。字节码指的是doSmth()Z方法。
  • 在运行时,doSmth()Z找不到该方法。而是找到了返回 Collection 的方法。

要更正此问题,请检查您的(编译时)类路径。

于 2010-09-12T15:25:09.517 回答
4

当前的回复只是告诉你为什么失败。通常更好地知道如何解决问题。如前所述,问题通常是您构建了程序,但是在运行或导出它时,该库不包括在内。所以解决方案是...

如果您正在运行,请检查运行配置选择运行选项卡-> 运行配置-> 选择您正在运行的配置-> 检查类路径选项卡-> 确保您需要的库在那里

如果要导出(例如war文件),请按照此选择项目->选择属性->选择部署程序集->按添加->选择Java构建路径条目->选择要包含在导出文件中的库(例如战争文件)

在这两种情况下,请确保包含您引用的库。

此错误的其他常见问题不是正确的参数类型或可见性,但是编译器会在运行之前检测到错误。在这种情况下,只需检查文档以匹配函数和包的可见性,并确保在项目属性的 Java 构建路径中找到该库。

于 2013-04-08T10:24:50.583 回答
3

也许仍然可以帮助某人,但是当您在类路径上有两个具有相同确切签名但它们没有相同公共方法的不同 jar 文件中的类时,也会发生此异常。

例如:

  • 在文件 mylibrary1.jar 你有类 com.mypackage.mysubpackage.MyClass 方法 doSmth()

  • 在 mylibrary2.jar 文件中,您有没有方法 doSmth()的类 com.mypackage.mysubpackage.MyClass

搜索类时,类加载器可能会根据路径优先级找到第一个 mylibrary2.jar,但找不到该类的方法。

确保您在两个不同的文件上没有相同的包 + 类。

于 2015-11-10T15:35:45.957 回答
2

在从 Eclipse 中的 SVN 更新它们之后,我在测试多个链接项目中的一些实验性更改时注意到了这个问题。

具体来说,我从 SVN 更新了所有项目,并恢复了 .classpath 文件,而不是手动编辑它以保持简单。

然后我将链接的项目重新添加到路径中,但忘记删除相关的 jar。这就是问题发生在我身上的原因。

显然,运行时使用了 jar 文件,而编译器使用了项目文件。

于 2012-01-27T19:21:25.203 回答
0

另一种可能发生并且很难找到的方式:

如果外部 jar 中的方法签名发生更改,因为在 IDE 中没有发现错误,因为它仍然与您调用它的方式兼容,则可能不会重新编译该类。

如果您的构建检查文件是否有更改,然后才重新编译它们,则在构建过程中可能不会重新编译该类。

因此,当您运行它时,这可能会导致该问题。虽然你有新的 jar,但你自己的代码仍然需要旧的,但从不抱怨。

为了使它更难,它取决于jvm是否可以处理这种情况。所以在最坏的情况下,它在测试服务器上运行,而不是在现场机器上。

于 2015-05-08T21:23:37.007 回答