我得到一个NoSuchMethodError错误时运行我的Java程序。出了什么问题,我该怎么解决?


当前回答

我通过重命名一个Junit测试文件在Eclipse中解决了这个问题。 在我的Eclipse工作空间中,我有一个App项目和一个Test项目。 Test项目将App项目作为构建路径上的必需项目。

开始获取NoSuchMethodError。 然后我意识到Test项目中的类与App项目中的类具有相同的名称。

App/  
  src/
     com.example/  
       Projection.java
Test/  
  src/
     com.example/
       Projection.java

在将测试重命名为正确的名称“ProjectionTest.java”后,异常消失了。

其他回答

我也遇到过类似的问题。

Caused by: java.lang.NoSuchMethodError: com.abc.Employee.getEmpId()I

最后,我发现根本原因是改变了变量的数据类型。

java——>包含数据类型从int改为String的变量(EmpId)。 使用getter getEmpId()检索值。

我们应该通过只包含修改过的类来重新打包jar。由于在ReportGeneration.java中没有任何变化,我只是在Jar文件中包含了Employee.class。我必须在jar中包含ReportGeneration.class文件来解决这个问题。

在我的情况下,我有一个多模块项目和场景像com.xyz.TestClass是在模块a,以及在模块B和模块a依赖于模块B。因此,创建一个程序集jar,我认为只有一个版本的类被保留,如果没有调用的方法,然后我得到NoSuchMethodError运行时异常,但编译是好的。

相关网址:https://reflectoring.io/nosuchmethod/

我在更改应用程序中的方法签名时遇到了类似的问题。 清理和重建我的项目解决了“NoSuchMethodError”。

我也遇到过这种错误。

我的问题是我改变了一个方法的签名,就像这样

void invest(Currency money){...}

void invest(Euro money){...}

从类似于的上下文调用此方法

public static void main(String args[]) {
    Bank myBank = new Bank();

    Euro capital = new Euro();
    myBank.invest(capital);
}

编译器对警告/错误保持沉默,因为资本既是货币也是欧元。

出现问题的原因是,我只编译了定义方法的类- Bank,而没有编译调用方法的类,其中包含main()方法。

您可能不会经常遇到这个问题,因为最常见的情况是手动重新构建项目或自动触发Build操作,而不仅仅是编译一个修改过的类。

我的用例是,我生成了一个.jar文件,它是用来作为一个热修复,不包含App.class,因为这是没有修改。对我来说,不包含它是有意义的,因为我通过继承保留了初始参数的基类。

问题是,当你编译一个类时,产生的字节码是静态的,换句话说,它是一个硬引用。

原始的分解字节码(由javap工具生成)如下所示:

 #7 = Methodref          #2.#22         // Bank.invest:(LCurrency;)V

在ClassLoader加载新的编译后的Bank.class后,它将找不到这样一个方法,它看起来好像它被删除了而没有被更改,因此出现了命名错误。

希望这能有所帮助。

这也可以是使用反射的结果。如果你的代码反映了一个类,并通过名称提取了一个方法(例如:with class。getDeclaredMethod("someMethodName", .....)),那么每当方法名称发生变化时,例如在重构期间,您将需要记住更新反射方法的参数以匹配新的方法签名,否则getDeclaredMethod调用将抛出NoSuchMethodException。

如果这是原因,那么堆栈跟踪应该显示调用反射方法的点,您只需要更新参数以匹配实际的方法签名。

根据我的经验,当单元测试私有方法/字段,并使用TestUtilities类提取字段以进行测试验证时,偶尔会出现这种情况。(通常在设计时没有考虑到单元测试的遗留代码。)