踩坑1:java.lang.IncompatibleClassChangeError: Expected static method总结

文章讨论了在Java中遇到IncompatibleClassChangeError异常的情况,主要是由于静态与非静态方法调用不匹配导致。当类的静态方法被误改为非静态,或者反之,且仅更新了被调用的方法而未更新所有依赖它的类时,会导致此问题。解决方案包括统一修改方法为静态或非静态并重新编译所有相关类,或者确保每次部署时所有依赖都同步更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

踩坑了吗,Eric带你避坑。

假设小明遇到下面的问题:

1.java.lang.IncompatibleClassChangeError: Expected static method

2.java.lang.IncompatibleClassChangeError: Expected non-static method

从报错的核心意思看,由于不兼容的Class.

什么情况下会小明遇到上述问题呢?

遇到问题1的场景:

假如小明有DateUtil.java

其中有个strToDate方法。这里我们假设使用Spring注入。

@Service("dateUtil")
public class DateUtil{
 public static Date strToDate(String date,String format) throws ParseException { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); 
Date formatDate = simpleDateFormat.parse(date); return formatDate; }
}

然后我们有个调用类TestDate.java

随便写个方法调用DateUtil.strToDate()方法。

@Autowired
@Qualifier("dateUtil")
DateUtil dateUtil;

public class TestDate{
public void formatDate(){

System.out.println(DateUtil.strToDate("2023-06-06","yyyy-MM-dd"));

}

public static void main(String [] args){

   TestDate testDate = new TestDate();
   testDate.formatDate();

}

}

现在开始编译代码,执行,一切都顺滑有序,没有问题。

突然不知道处于什么原因,小明鬼使神差地将DateUtil.strToDate方法变成了非static方法,即去掉了static关键字。然后编译代码,执行。这也没问题。重点来了,小明的项目是通过class文件部署的。他本次代码改完后,就只将DateUtil部署了上去。然后执行,就出现了异常:

Exception in thread "Thread-1" java.lang.IncompatibleClassChangeError: Expecting static method

此时将TestDate.class文件反编译。看到代码如下

System.out.println(DateUtil.strToDate("2023-06-06","yyyy-MM-dd"));

可以看出调用方法使用了类调用,即应该调用static方法。

遇到问题2的场景:

好下面的问题刚好相反。

小明看到异常提醒,说expect static,所以小明将上述方法改回了static

但此时,刚好小红开发了另一个类TestDate2.java的formatDate()也调用了DateUtil.strDate方法。小红同样也按部就班,编译代码,本地执行,部署,都没问题。

​
@Autowired
@Qualifier("dateUtil")
DateUtil dateUtil;

public class TestDate2{
public void formatDate(){


System.out.println(dateUtil.strToDate("2023-06-06","yyyy-MM-dd"));

}

public static void main(String [] args){

   TestDate testDate = new TestDate();
   testDate.formatDate();

}

}

​

小明这时候也仅仅将DateUtil.java编译后部署了上去。结果:小红的TestDate2的formatDate()抛出异常:

Exception in thread "Thread-1" java.lang.IncompatibleClassChangeError: Expecting non-static method

为什么呢?

可以通过分析小红的TestDate2.calss.

反编译后,小红调用的代码长这个样子:

System.out.println(this.dateUtil.strToDate("2023-06-06","yyyy-MM-dd"));

也就是说,小红的代码,此时是通过对象调用,而不是类调用调用了strToDate方法。

解决方案:

最终,小明,小红商定使用方案1:

1.将DateUtil.strToDate改为static

2.remove掉调用方法里的Spring注入的属性,直接使用类调用,并把所有的编译class重新部署。

方案2:

1.如果使用DateUtil.strToDate为非static方法,要将所有的调用该方法的类都要重新编译部署。

2.使用对象的方式进行调用。

总结:

1.什么情况下会遇到这个问题:编译时,如果被调用方法是static, 调用类的编译结果是类调用即DateUtil.strTodate(..); 反之,如果被调用方法时非static类,调用类编译结果是对象调用,即this.dateUtil.strToDate(..); 如果实际部署的工具类DateUtil和编译时的版本不一致,则会出现本文的问题。

2.统一编译打包的项目一般不会遇到该问题。通过class部署的项目,当如工具类DateUtil修改并编译后,没有将所有调用类重新部署,就会遇到该问题。

本文代码没有通过项目演示,均为作者在页面手敲,如果觉得有不明的或错误之处,还望指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值