Question

Je suis très nouveau sur processing.org et Java. J'essaie de stocker des objets dans un HashMap, puis d'itérer les valeurs du HashMap en appelant des méthodes sur les objets stockés. Afin de faire cela, je suppose que je dois convertir l'itérateur au type de ma classe, mais cela jette une exception ClassCastException ("java.util.HashMap $ ValueIterator ne peut pas être converti en sketch_oct27a $ MyClass"). Le code simplifié suivant illustre ce comportement:

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

Comment appeler la méthode SaySomething () via l'itérateur?

Était-ce utile?

La solution

Voici comment vous utilisez un itérateur:

((MyClass)iter.next()).SaySomething();

Mieux encore, utilisez les génériques pour ne pas avoir à lancer du tout:

HashMap<MyClass> m = new HashMap<MyClass>();
...
Iterator<MyClass> iter = m.values().iterator();
...
iter.next().SaySomething();

Vous pouvez alors même ignorer complètement l'itérateur (en fait, cette syntaxe le cache, il est toujours utilisé de manière implicite):

for(MyClass element : m.values())
{
    element.SaySomething();
}

Autres conseils

Votre code fait actuellement ceci:

    ((MyClass)iter).SaySomething();

Ceci indique que "cast iter " est une instance de MyClass et appelle sa méthode SaySomething () . Cela échoue car la classe réelle de l'instance iter sera une classe interne qui implémente l'interface java.util.Iterator . Cette classe ne sera pas une sous-classe de MyClass.

Ce que vous devez faire est d’obtenir que l’itérateur fournisse sa valeur suivante et qu’il lance cette valeur; c'est-à-dire

    ((MyClass) (iter.next())).SaySomething();

que vous pouvez simplifier:

    ((MyClass) iter.next()).SaySomething();

en raison de la priorité des opérateurs Java.

@Michael fait remarquer que si vous utilisez des génériques, vous pouvez vous débarrasser de la conversion de type manifeste. Vous pouvez simplifier encore davantage en utilisant le " nouveau " pour la syntaxe de boucle introduite dans 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 réalité, la boucle for est un sucre syntaxique. Sous les couvertures, l'instance Iterator est créée et utilisée conformément à votre code (avec la correction). Même la conversion de type est en cours d'exécution ... à moins que le JIT ne sache qu'il peut l'optimiser à distance.

EDIT: si vous ne pouvez pas utiliser Java 1.5, vous ne pourrez plus le faire à l'ancienne. Cela ressemble à & processing; processing.org " doit obtenir leur acte ensemble. La plate-forme Java 1.4.x est vraiment obsolète.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top