前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入分析ClassCastException

深入分析ClassCastException

作者头像
PhoenixZheng
发布2018-08-07 16:41:51
5860
发布2018-08-07 16:41:51
举报
庖丁解牛--ClassCastException

ClassCastException时常见,只要两个不同类强转换就会有这种问题,不过下面这种错误不知道见过没

Caused by: java.lang.ClassCastException: Socker cannot be cast to Socker at Socker.setInstance(Socker.java:10) … 6 more

说明一下,前后两个Socker是同一个类的不同对象,来看看是怎么弄出这个错误的,我们用的还是昨天自定义ClassLoader的代码

代码语言:javascript
复制
public class Ming {

  public static void main(String[] args) {
    System.out.println("Ming looking for socker");
    checkClassCast();
  }

  private static void checkClassCast() {
    try {
      DiskClassLoader loader1 = new DiskClassLoader("../WangHouse");
      DiskClassLoader loader2 = new DiskClassLoader("../WangHouse");

      Class class1 = loader1.findClass("Socker");
      Class class2 = loader2.findClass("Socker");

      Object socker1 = class1.newInstance();
      Object socker2 = class2.newInstance();

      Method method = class1.getDeclaredMethod("setInstance", Object.class);
      method.invoke(socker1, socker2);
      } catch(Exception e){
      e.printStackTrace();
    }
  }
}
代码语言:javascript
复制
public class Socker {
  private Socker mInstance;

  public void setInstance(Object socker) {
    System.out.println("Socker set");
    this.mInstance = (Socker)socker;
  }
}

我们构造了两个DiskClassLoader对象,分别加载了同一个Socker类实例化两个对象,然后用反射把其中一个通过set方法注入给另外一个Socker对象。

然后异常就发生了。

是不是没道理?明明都是Socker类的对象,这种转换都不行的吗?

JVM对类的判定

其实原因很简单,在JAVA中,判断两个类是否相同,不仅要判断类名,还要判断是否由同一个ClassLoader加载的。上面的代码中因为我们实例化了两个ClassLoader,两个Socker对象在不同的ClassLoader中,因此不满足类相同的条件,就不能转换。

如果把代码调整一下变成用同一个ClassLoader加载的话

代码语言:javascript
复制
private static void checkClassCast() {
  try {
    DiskClassLoader loader1 = new DiskClassLoader("../WangHouse");
    // DiskClassLoader loader2 = new DiskClassLoader("../WangHouse");

    Class class1 = loader1.findClass("Socker");
    // Class class2 = loader2.findClass("Socker");

    Object socker1 = class1.newInstance();
    Object socker2 = class1.newInstance();

    Method method = class1.getDeclaredMethod("setInstance", Object.class);
    method.invoke(socker1, socker2);
    } catch(Exception e){
    e.printStackTrace();
  }
}

输出结果如下

Ming looking for socker Socker set

这样就可以了。

总结

通常在开发中我们不会遇到这种奇葩问题。不过如果在Android开发涉及到热修复的时候,就有可能遇到这种问题了。 一般场景是自定义了一个ClassLoader用来加载插件dex,而主Loader中又加载了相同的类,那么就有可能发生这种问题。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android每日一讲 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 庖丁解牛--ClassCastException
  • JVM对类的判定
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档