ClassCastException при приведении итератора HashMap к конкретному типу - PullRequest
0 голосов
/ 27 октября 2009

Я очень новичок в processing.org и Java. Я пытаюсь сохранить объекты в HashMap, а затем перебрать значения HashMap, вызывая методы для хранимых объектов. Для этого я предполагаю, что мне нужно уменьшить итератор до типа моего класса, но это вызывает исключение ClassCastException («java.util.HashMap $ ValueIterator не может быть приведен к sketch_oct27a $ MyClass»). Следующий упрощенный код демонстрирует это поведение:

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

Как вызвать метод SaySomething () через итератор?

Ответы [ 2 ]

6 голосов
/ 27 октября 2009

Вот как вы используете итератор:

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

Еще лучше, используйте Generics, чтобы вам вообще не приходилось разыгрывать:

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

Затем можно даже полностью пропустить итератор (фактически этот синтаксис просто скрывает его, он все еще используется неявно):

for(MyClass element : m.values())
{
    element.SaySomething();
}
2 голосов
/ 27 октября 2009

Ваш код в настоящее время делает это:

    ((MyClass)iter).SaySomething();

Это говорит "приведение iter в качестве экземпляра MyClass и вызов его метода SaySomething(). Это не удается, потому что фактическим классом экземпляра iter будет некоторый внутренний класс, который реализует интерфейс java.util.Iterator. Этот класс не будет подклассом MyClass.

Что вам нужно сделать, это заставить итератор доставить его следующее значение и привести это значение; т.е.

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

который вы можете упростить до:

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

из-за приоритета оператора Java.

@ Майкл указывает, что если вы используете дженерики, вы можете избавиться от явного типа трансляции. Вы можете упростить еще больше, используя «новый» для синтаксиса цикла, представленный в 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(); 
    }

На самом деле цикл for - это просто синтаксический сахар. Под прикрытием создается экземпляр Iterator, который используется в соответствии с вашим кодом (с исправлением). Даже выполняется приведение типа ... если JIT не может выяснить, что он может оптимизировать его.

РЕДАКТИРОВАТЬ: если вы не можете использовать Java 1.5, то вы застряли с этим по старинке. Похоже, что "processing.org" должен собрать их акт. Платформа Java 1.4.x действительно устарела.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...