无法强制转换为已实现的界面

时间:2011-11-07 11:32:22

标签: java inheritance classcastexception

我很困惑......

我有一个直接实现接口的类:

public class Device implements AutocompleteResult
{...}

以下是我正在查看正确变量的证明:

Object match = ...;
log.debug(match.getClass()); // Outputs 'Device'
log.debug(match.getClass().getInterfaces()[0]); // Outputs 'AutocompleteResult'

然而,当我尝试将类的实例强制转换为接口时:

AutocompleteResult result = (AutocompleteResult) match;

我得到了ClassCastException!

ClassCastException: Device cannot be cast to AutocompleteResult

此外,isAssignableFrom返回false,我不确定原因:

log.debug(AutocompleteResult.class.isAssignableFrom(Device.class));

来自doc

  

确定此Class对象所表示的类或接口是否与所表示的类或接口相同,或者是超类或超接口通过指定的Class参数。

我不应该总是能够将对象强制转换为其类实现的接口吗?

感谢。

2 个答案:

答案 0 :(得分:63)

如果两个不同的类加载器加载名为AutocompleteResult的类。

,就会发生这种情况

然后将这两个类视为完全不同的类,即使它们具有相同的包和名称(甚至是实现/字段/方法)。

这是一个常见原因,如果您使用某种插件系统,并且您的基类和插件类提供相同的类。

要检查此问题,请打印Class.getClassLoader()在两个有问题的类(即Device 实现的接口的类和的结果{{1}上返回的值}})。

答案 1 :(得分:0)

当Java显然不是Java时,

AKA。

我最近使用Play Framework 2.6.3解决了这个问题,对我有帮助的是: https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader

我将此信息保留给可能遇到同样问题的人。

为了更清楚,有用的是:

在Eager Singleton上注入应用程序,然后使用其类加载器加载我遇到问题的类。

使其更清晰

public class Module {


 @Override
 public void configure {
   bind(TheClassLoaderLoader.class).asEagerSingleton()

public static class TheClassLoaderLoader {
  @Inject
        public TheClassLoaderLoader( Application application) {

         ClassLoader classloader = application.classloader();

                Class<?> interfaceClass = classloader.loadClass(InterfaceClass.class.getName());
                classloader.loadClass(ImplementsInterfaceClass.class.getName()).asSubclass(interfaceClass);

此处的示例https://playframework.com/documentation/2.6.x/JavaDependencyInjection#Configurable-bindings

使用Environment经常会引起令人沮丧的ClassNotFoundException

干杯