我很困惑......
我有一个直接实现接口的类:
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参数。
我不应该总是能够将对象强制转换为其类实现的接口吗?
感谢。
答案 0 :(得分:63)
如果两个不同的类加载器加载名为AutocompleteResult
的类。
然后将这两个类视为完全不同的类,即使它们具有相同的包和名称(甚至是实现/字段/方法)。
这是一个常见原因,如果您使用某种插件系统,并且您的基类和插件类提供相同的类。
要检查此问题,请打印Class.getClassLoader()
在两个有问题的类(即Device
实现的接口的类和的结果{{1}上返回的值}})。
答案 1 :(得分:0)
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
干杯