2012-03-25 29 views
8

Estoy recorriendo ArrayList<Bar>. Foo extiende Bar. Estoy tratando de encontrar una instancia de Foo en la lista.Foo no se puede convertir 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; 
    } 
} 

Si esta sección del código se ejecute me sale este error:

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

Sin embargo, en otro lugar, tengo un método que devuelve una instancia de Bar y puedo comprobar para ver si se trata de una instancia de Foo usando instanceof y luego fundido Bar a Foo sin problemas:

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

¿Qué es diferente aquí?

Aquí es el verdadero origen del problema: http://pastie.org/private/jhyhovn7mm4ghxlxsmweog

Estoy trabajando con una API llamada Bukkit que permite plugins personalizados para los servidores para un juego llamado Minecraft. La documentación se puede encontrar here para aquellos realmente interesados ​​en el tema. Iré a los foros oficiales de Bukkit y probaré mi pregunta allí, ya que se está convirtiendo más en un problema específico de API, pero dejaré todo esto aquí para aquellos que estén interesados ​​en el problema.

+0

¿ambos heredan de la misma clase base? – Asdfg

+0

@Asdfg * They * being what? –

+0

¿podría proporcionar la demostración de IDEOne para su problema? http://ideone.com –

Respuesta

17

Supongo que está cargando Foo desde dos lugares. En su ciclo, intente imprimir bar.getClass().getClassLoader() y Foo.class.getClassLoader(). Sospecho que mostrarán diferentes clasificadores. (Es posible que tenga dos cargadores de clases cargando desde el mismo lugar, por supuesto, que es igual de malo.)

Básicamente, en lo que respecta a la JVM, dos clases con el mismo nombre cargadas de diferentes cargadores de clases son completamente diferente: no se puede transmitir de uno a otro. Suponiendo que tengo razón en esto, la solución habitual es intentar averiguar por qué se están cargando desde diferentes cargadores de clases, y solucionarlo.

Tenga en cuenta que cuando se utiliza instanceof lugar, que comprueba si los tipos son realmente compatibles, por lo que se Aviso los cargadores de clases diferentes.

+1

Parece una buena probabilidad. Si instanceof está fallando, forzar el problema por su nombre no es probable que lo arregle, solo ayuda a revelar el problema subyacente. También he visto este problema en una compilación sucia, asegúrate de haber limpiado la compilación a fondo. Esto también puede suceder si tienes archivos conflictivos con com.me.Foo también, creo. – PlexQ

+0

Todavía no me he encontrado con esta situación. ¿Cuál podría ser el motivo por el que jvm elige un cargador de clases diferente por sí mismo? –

+2

@JigarJoshi: puede ser un problema en webapps, donde se ejecutan diferentes códigos de diferentes cargadores de clases, que terminan por complicarse bastante.(Suele suceder con las clases de biblioteca, por ejemplo, si tiene log4j en un archivo de guerra * y * en el cargador de clases de contenedor). –

Cuestiones relacionadas