2012-03-25 3 views
8

Я перебираю ArrayList<Bar>. Foo распространяется Bar. Я пытаюсь найти экземпляр Foo в списке.Foo нельзя отнести к Foo

ArrayList<Bar> list = new ArrayList<Bar>(); 

// fill list with items that are instances of Foo and Bar 

for (int i = 0; i < list.size(); i++) 
{ 
    Bar bar = list.get(i); 

    if (bar.getClass().getName().equals("com.me.Foo")) // "if(bar instanceof Foo)" never passes 
    { 
    System.out.println("bar is an instance of Foo"); 
    Foo foo = (Foo) bar; 
    } 
} 

Если этот раздел кода получает запустить я получаю эту ошибку:

java.lang.ClassCastException: com.me.Foo cannot be cast to com.me.Foo 
// stack 

Однако в другом месте, у меня есть метод, который возвращает экземпляр Bar и я могу проверить, если это экземпляр Foo с помощью instanceof и затем отливали Bar к Foo без проблем:

Bar bar = returnBar(); // returns an instance of Bar, but the variable 
         // it returns could be an instance of Foo 
if (bar instanceof Foo) 
{ 
    System.out.println("bar is an instance of Foo"); 
    Foo foo = (Foo) bar; 
} 

Что здесь такое?

Вот реальный источник вопроса: http://pastie.org/private/jhyhovn7mm4ghxlxsmweog

Я работаю с API под названием Bukkit, который позволяет для пользовательских подключаемых модулей для серверов для игры под названием Minecraft. Документация может быть найдена here для тех, кто действительно интересуется этой проблемой. Я собираюсь пойти на официальные форумы Bukkit и попробовать свой вопрос там, так как он становится больше проблемой API, но я оставлю все это здесь для тех, кто интересуется этой проблемой.

+0

Они оба наследуют от того же базового слоя? – Asdfg

+0

@Asdfg * Они * были чем? –

+0

не могли бы вы предоставить демо-версию IDEOne для своей проблемы? http://ideone.com –

ответ

17

Я предполагаю, что вы загружаете Foo из двух мест. В вашей петле попробуйте распечатать bar.getClass().getClassLoader() и Foo.class.getClassLoader(). Я подозреваю, что они будут показывать разные загрузчики классов. (Возможно, вы загрузили два загрузчика классов с одного и того же места, что одинаково плохо.)

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

Обратите внимание, что при использовании instanceof вместо этого проверяется, действительно ли типы совместимы, поэтому будет Обратите внимание на различные загрузчики классов.

+1

Похоже на хорошую вероятность. Если instanceof не работает, форсирование проблемы по имени вряд ли может ее исправить, просто помогите выявить основную проблему. Я также видел эту проблему в грязной сборке, убедитесь, что вы тщательно очистили сборку. Это также может произойти, если у вас конфликтующие банки с com.me.Foo тоже я верю. – PlexQ

+0

Я еще не сталкивался с такой ситуацией, что может быть причиной того, что jvm сам выбирает разного загрузчика классов? –

+2

@JigarJoshi: Это может быть проблема в webapps, где у вас есть другой код, запущенный от разных загрузчиков классов, которые в конечном итоге становятся довольно сложными.(Это часто случается с библиотечными классами - например, если у вас есть log4j как в военном файле, так и в * контейнере-загрузчике классов.) –