将HashMap迭代器转换为具体类型时出现ClassCastException

时间:2009-10-26 22:46:47

标签: java iterator hashmap processing

我对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 个答案:

答案 0 :(得分:6)

这是你使用迭代器的方法:

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

更好的是,使用泛型,以便你根本不需要施放:

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

然后你甚至可以完全跳过迭代器(实际上,这个语法只是隐藏它,它仍然是隐式使用的):

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

答案 1 :(得分:2)

您的代码目前正在执行此操作:

    ((MyClass)iter).SaySomething();

这表示“将iter作为MyClass的实例并调用其SaySomething()方法。这会失败,因为iter实例的实际类将是某个内部类实现接口java.util.Iterator。该类不是MyClass的子类。

您需要做的是让迭代器提供下一个值,然后转换该值;即。

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

你可以简化为:

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

因为Java运算符优先。

@Michael指出,如果你使用泛型,你可以摆脱公开的类型转换。您可以使用Java 5.0中引入的“new”for循环语法进一步简化:

    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平台真的已经过时了。