2011-11-07 62 views
29

我很困惑...无法投射到实现的接口

我有直接实现接口的类:

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,我不知道为什么:

​​

doc

判定此类类或接口代表对象是或者是相同的,或者是超类或者是superinterf ace,由指定的Class参数表示的类或接口。

我不应该总是能够投出对象的接口的类实现的?

谢谢。

+0

是的,你应该! (你甚至不需要明确的转换。)请张贴一些自包含的示例代码来演示问题。 –

回答

54

如果两个不同的类加载器加载一个名为AutocompleteResult类可能发生这种情况。

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

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

要检查这个问题,打印由Class.getClassLoader()两个违规类返回的值(即类的DeviceAutocompleteResult.class结果实现的接口)。

+1

哇,谢谢!我真的在这一张上撕下了头发。我会尝试解决类加载问题,现在... – pstanton

+3

+1:尝试'log.debug(match.getClass()。getInterfaces()[0] .getClassLoader()); log.debug(AutocompleteResult.class.getClassLoader())' –

+0

我的问题是我有错误的导入类,这有助于我确定:'Class [] interfaces = match.getClass()。getInterfaces(); for(int i = 0; i toobsco42

0

AKA时的Java显然不会的Java。

我最近袭击了这个问题,播放框架2.6.3,是什么帮助我是这样的: https://www.playframework.com/documentation/2.6.x/ThreadPools#Application-class-loader

我离开这里了这个信息对于可能有同样的问题的人。

使其更清晰,有什么可以帮助是:

注入上的渴望辛格尔顿应用程序,然后使用它的类加载器加载我是有问题的类。

使其更清晰

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

干杯