2012-03-25 15 views
8

Sto passando attraverso ArrayList<Bar>. Foo estende Bar. Sto cercando di trovare un'istanza di Foo nell'elenco.Foo non può essere trasmesso a 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; 
    } 
} 

Se questa sezione di codice viene eseguito ottengo questo errore:

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

Tuttavia, in un altro posto, ho un metodo che restituisce un'istanza di Bar e posso controllare per vedere se si tratta di un'istanza di Foo utilizzando instanceof e poi gettato Bar a Foo senza problemi:

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; 
} 

Cosa c'è di diverso qui?

Ecco la vera fonte del problema: http://pastie.org/private/jhyhovn7mm4ghxlxsmweog

Sto lavorando con un'API chiamata Bukkit che permette di plugin personalizzati per i server per un gioco chiamato Minecraft. La documentazione può essere trovata here per quelli veramente interessati al problema. Vado nei forum ufficiali di Bukkit e provo la mia domanda lì, poiché sta diventando più un problema specifico dell'API, ma lascerò tutto questo qui per coloro che erano interessati al problema.

+0

entrambi ereditano dalla stessa baseclass? – Asdfg

+0

@Asdfg * Loro * essere cosa? –

+0

potresti fornire la demo IDEOne per il tuo problema? http://ideone.com –

risposta

17

La mia ipotesi è che stai caricando Foo da due posti. Nel tuo ciclo, prova a stampare bar.getClass().getClassLoader() e Foo.class.getClassLoader(). Sospetto che mostreranno diversi classloader. (È possibile che tu abbia due caricatori di classe che caricano dallo stesso posto, ovviamente, il che è altrettanto brutto.)

Fondamentalmente, per quanto riguarda la JVM, due classi con lo stesso nome caricate da diversi classloader sono completamente diverso - non puoi trasmettere l'uno all'altro. Supponendo che abbia ragione su questo, la solita soluzione è provare a risolvere perché vengono caricati da diversi classloader e risolvere il problema.

Si noti che quando si utilizza instanceof invece, che controlla se i tipi sono realmente compatibili, quindi sarà notare i diversi programmi di caricamento classi.

+1

Sembra una buona probabilità. Se l'instanceof sta fallendo, forzare il problema per nome non è in grado di risolverlo, basta aiutare a svelare il problema sottostante. Ho anche visto questo problema in una build sporca, assicurati di aver pulito accuratamente la build. Questo può anche accadere se si hanno barattoli in conflitto con com.me.Foo anche io credo. – PlexQ

+0

Non ho ancora incontrato una situazione del genere, quale potrebbe essere la ragione per cui jvm sceglie diversi caricatori di classi da solo? –

+2

@JigarJoshi: Può essere un problema nelle webapps, dove hai codice diverso eseguito da vari diversi classloader, che finiscono per diventare piuttosto complicato.(Accade spesso con le classi di libreria, ad esempio se hai log4j sia in un file war * che in * il classloader del contenitore.) –

Problemi correlati