не может быть приведен к реализованному интерфейсу - PullRequest
37 голосов
/ 07 ноября 2011

Я очень запутался ...

У меня есть класс, который непосредственно реализует интерфейс:

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 ]

63 голосов
/ 07 ноября 2011

Это может произойти, если два разных загрузчика классов загрузят класс с именем AutocompleteResult.

Эти два класса затем обрабатываются как совершенно разные классы, даже если они имеют одинаковый пакет и имя (и даже реализацию / поля / методы).

Распространенной причиной этого является случай, когда вы используете какую-то систему плагинов и ваши базовые классы и классы плагинов предоставляют один и тот же класс.

Для проверки этой проблемы выведите значение, возвращаемое Class.getClassLoader() в обоих классах-нарушителях (т. Е. Класс интерфейса, реализованный Device и , результатом AutocompleteResult.class).

0 голосов
/ 17 октября 2017

АКА, когда 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

Приветствия

...