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

踩坑了吗,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修改并编译后,没有将所有调用类重新部署,就会遇到该问题。

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值