ClassCastException quando casting HashMap Iterator a um tipo concreto
-
06-07-2019 - |
Pergunta
Eu sou muito novo para processing.org e Java. Eu estou tentando armazenar objetos em um HashMap, e depois repetir os valores do HashMap, chamando métodos nos objetos armazenados. A fim de fazer isso, presumo eu preciso para downcast o iterador para o tipo de minha classe, mas isto lança uma ClassCastException ( "java.util.HashMap $ ValueIterator não pode ser convertido para sketch_oct27a $ MyClass"). O código simplificado a seguir demonstra esse comportamento:
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");
}
}
Como faço para chamar o método SaySomething () através do iterador?
Solução
Esta é a forma como você usa um iterador:
((MyClass)iter.next()).SaySomething();
Melhor ainda, usar os genéricos para que você não tem que elenco em tudo:
HashMap<MyClass> m = new HashMap<MyClass>();
...
Iterator<MyClass> iter = m.values().iterator();
...
iter.next().SaySomething();
Você pode então mesmo pular o iterador inteiramente (na verdade, esta sintaxe apenas esconde-lo, ele ainda é usado implicitamente):
for(MyClass element : m.values())
{
element.SaySomething();
}
Outras dicas
Seu código atualmente faz isso:
((MyClass)iter).SaySomething();
Este diz "iter
elenco como uma instância de MyClass
e chamar seu método SaySomething()
. Esta falha porque a classe real da instância iter
serão alguns classe interna que implementa a interface java.util.Iterator
. Essa classe não será uma subclasse de MyClass.
O que você precisa fazer é obter o iterador para entregar seu próximo valor e elenco que valor; i.
((MyClass) (iter.next())).SaySomething();
que você pode simplificar a:
((MyClass) iter.next()).SaySomething();
por causa do Java precedência do operador.
@ Michael assinala que se você usar os genéricos você pode se livrar do typecast evidente. Você pode simplificar ainda mais usando o "novo" para a sintaxe de loop introduzido em 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();
}
Na realidade, o loop é apenas açúcar sintático. Debaixo das cobertas, a instância Iterator está sendo criado e usado de acordo com o seu código (com a correção). Mesmo o tipo elenco está sendo realizado ... a menos que o JIT pode descobrir que ele pode otimizar-lo.
EDIT: se você não pode usar Java 1.5, então você está preso com isso da maneira old-fashioned. Soa como necessidades "processing.org" para obter a sua juntos ato. A plataforma Java 1.4.x é realmente fora da data.