我正在循环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;
}
}
如果此部分代码运行,我会收到此错误:
java.lang.ClassCastException: com.me.Foo cannot be cast to com.me.Foo
// stack
但是,在另一个地方,我有一个返回Bar
实例的方法,我可以使用Foo
检查它是否是instanceof
的实例,然后转换{{ 1}}到Bar
没有问题:
Foo
这里有什么不同?
以下是该问题的真正来源: http://pastie.org/private/jhyhovn7mm4ghxlxsmweog
我正在使用一个名为Bukkit的API,它允许为名为Minecraft的游戏提供服务器的自定义插件。对于那些对此问题真正感兴趣的人,可以找到here文档。我将去官方Bukkit论坛并在那里尝试我的问题,因为它变得更具API特定问题,但我会把这一切留给那些对这个问题感兴趣的人。
答案 0 :(得分:17)
我的猜测是你从两个地方加载Foo
。在循环中,尝试打印bar.getClass().getClassLoader()
和Foo.class.getClassLoader()
。我怀疑他们会展示不同的类加载器。 (你可能有两个类加载器从同一个地方加载,当然,这同样很糟糕。)
基本上,就JVM而言,从不同类加载器加载的两个具有相同名称的类完全不同 - 您不能从一个类转换为另一个类。假设我是对的,通常的解决方案是尝试解决为什么从不同的类加载器加载它们并修复它。
请注意,当您使用instanceof
时,会检查这些类型是否真正兼容,因此 会注意到不同的类加载器。