Foo无法投射到Foo

Aus*_*ore 8 java casting

我正在循环ArrayList<Bar>.Foo延伸Bar.我正在尝试Foo在列表中找到一个实例.

ArrayList<Bar> list = new ArrayList<Bar>();

// fill list with items that are instances of Foo and Bar

for (int i = 0; i < list.size(); i++)
{
  Bar bar = list.get(i);

  if (bar.getClass().getName().equals("com.me.Foo")) // "if(bar instanceof Foo)" never passes
  {
    System.out.println("bar is an instance of Foo");
    Foo foo = (Foo) bar;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果此部分代码运行,我会收到此错误:

java.lang.ClassCastException: com.me.Foo cannot be cast to com.me.Foo
// stack
Run Code Online (Sandbox Code Playgroud)

但是,在另一个地方,我有一个方法返回一个实例,Bar我可以检查它是否是一个Foo使用的实例instanceof然后Bar转换Foo为没有问题:

Bar bar = returnBar(); // returns an instance of Bar, but the variable 
                       // it returns could be an instance of Foo
if (bar instanceof Foo)
{
  System.out.println("bar is an instance of Foo");
  Foo foo = (Foo) bar;
}
Run Code Online (Sandbox Code Playgroud)

这有什么不同?

以下是该问题的真正来源:http: //pastie.org/private/jhyhovn7mm4ghxlxsmweog

我正在使用一个名为Bukkit的API,它允许为名为Minecraft的游戏提供服务器的自定义插件.可以在此处找到对该问题真正感兴趣的人员的文档.我将去官方Bukkit论坛并在那里尝试我的问题,因为它变得更具API特定问题,但我将把这一切留给那些对这个问题感兴趣的人.

Jon*_*eet 17

我的猜测是你Foo从两个地方装货.在你的循环,尝试打印出来bar.getClass().getClassLoader()Foo.class.getClassLoader().我怀疑他们会展示不同的类加载器.(你可能有两个类加载器从同一个地方加载,当然,这同样很糟糕.)

基本上,就JVM而言,从不同类加载器加载的两个具有相同名称的类完全不同 - 您不能从一个类转换为另一个类.假设我对此是正确的,通常的解决方案是尝试找出为什么他们从不同的类加载器加载,并解决它.

请注意,当您使用时instanceof,检查类型是否真正兼容,因此它注意到不同的类加载器.

  • @JigarJoshi:这可能是webapps中的一个问题,你可以从各种不同的类加载器中运行不同的代码,最终变得非常复杂.(它经常发生在库类中 - 例如,如果你在war文件*和*容器类加载器中都有log4j.) (2认同)