ClassCastException al convertir el iterador HashMap en un tipo concreto
-
06-07-2019 - |
Pregunta
Soy muy nuevo en processing.org y Java. Estoy tratando de almacenar objetos en un HashMap y luego iterar sobre los valores de HashMap, llamando a los métodos en los objetos almacenados. Para hacer eso, supongo que necesito bajar el iterador al tipo de mi clase, pero esto arroja una ClassCastException (" java.util.HashMap $ ValueIterator no se puede convertir en sketch_oct27a $ MyClass "). El siguiente código simplificado demuestra este comportamiento:
import java.util.*;
void setup() {
HashMap m = new HashMap();
m.put("First", new MyClass());
m.put("Second", new MyClass());
m.put("Third", new MyClass());
Iterator iter = m.values().iterator();
while (iter.hasNext()) {
((MyClass)iter).SaySomething(); // Throws ClassCastException
iter.next();
}
}
class MyClass {
void SaySomething() {
println("Something");
}
}
¿Cómo llamo al método SaySomething () a través del iterador?
Solución
Así es como usas un iterador:
((MyClass)iter.next()).SaySomething();
Mejor aún, use Generics para no tener que lanzar nada:
HashMap<MyClass> m = new HashMap<MyClass>();
...
Iterator<MyClass> iter = m.values().iterator();
...
iter.next().SaySomething();
Incluso puede omitir el iterador por completo (en realidad, esta sintaxis simplemente lo oculta, todavía se usa implícitamente):
for(MyClass element : m.values())
{
element.SaySomething();
}
Otros consejos
Su código actualmente hace esto:
((MyClass)iter).SaySomething();
Esto dice " cast iter
como una instancia de MyClass
y llama a su método SaySomething ()
. Esto falla porque la clase real de la instancia de iter
será alguna clase interna que implementa la interfaz java.util.Iterator
. Esa clase no será una subclase de MyClass.
Lo que debe hacer es hacer que el iterador entregue su próximo valor y emitir ese valor; es decir
((MyClass) (iter.next())).SaySomething();
que puede simplificar a:
((MyClass) iter.next()).SaySomething();
debido a la precedencia del operador Java.
@Michael señala que si usas genéricos puedes deshacerte de la escritura abierta. Puede simplificar aún más utilizando el " nuevo " para la sintaxis de bucle introducida en Java 5.0:
HashMap<String, MyClass> m = new HashMap<String, MyClass>();
m.put("First", new MyClass());
m.put("Second", new MyClass());
m.put("Third", new MyClass());
for (MyClass mc : m.values()) {
mc.SaySomething();
}
En realidad, el ciclo for es solo azúcar sintáctico. Debajo de las cubiertas, la instancia de Iterator se está creando y utilizando según su código (con la corrección). Incluso el tipo de conversión se está realizando ... a menos que el JIT pueda darse cuenta de que puede optimizarlo.
EDITAR: si no puede usar Java 1.5, entonces no puede hacerlo de la manera tradicional. Suena como " processing.org " necesita actuar juntos. La plataforma Java 1.4.x está realmente desactualizada.