【问题标题】:can't cast to implemented interface无法转换为已实现的接口
【发布时间】:2017-10-17 05:19:56
【问题描述】:

我很困惑……

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

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 参数。

难道我不应该总是能够将一个对象转换为它的类实现的接口吗?

谢谢。

【问题讨论】:

  • 是的,你应该! (你甚至不应该需要显式转换。)请发布一些演示问题的独立示例代码。

标签: java inheritance classcastexception


【解决方案1】:

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

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

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

要检查此问题,请在两个违规类上打印Class.getClassLoader() 返回的值(即Device 实现的接口类AutocompleteResult.class 的结果)。 p>

【讨论】:

  • 哇,谢谢!我真的把头发扯掉了。我现在将尝试解决类加载问题...
  • +1:试试log.debug(match.getClass().getInterfaces()[0].getClassLoader()); log.debug(AutocompleteResult.class.getClassLoader())
  • 我的问题是我输入了错误的类,这帮助我确定:Class[] interfaces = match.getClass().getInterfaces(); for(int i = 0; i < interfaces.length; i++){ Log.d(DEBUG_TAG, interfaces[i].toString()); Log.d(DEBUG_TAG, AutocompleteResult.class.toString()); }
【解决方案2】:

当 Java 显然不是 Java 时也称为。

我最近在使用 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

干杯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-08
    • 2010-12-08
    • 2019-07-26
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-24
    相关资源
    最近更新 更多