HashMapイテレータを具象型にキャストするときのClassCastException
-
06-07-2019 - |
質問
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()メソッドを呼び出す方法
解決
これがイテレータの使用方法です:
((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();
}
他のヒント
現在、あなたのコードはこれをしています:
((MyClass)iter).SaySomething();
これは、 MyClass
のインスタンスとして&quot; cast iter
を言い、その SaySomething()
メソッドを呼び出します。 iter
インスタンスの実際のクラスは、インターフェイス java.util.Iterator
を実装する内部クラスになるため、これは失敗します。そのクラスはMyClassのサブクラスにはなりません。
する必要があるのは、イテレータに次の値を提供させ、その値をキャストすることです。すなわち
((MyClass) (iter.next())).SaySomething();
これを単純化できます:
((MyClass) iter.next()).SaySomething();
Java演算子の優先順位のため。
@Michaelは、ジェネリックを使用すると、あからさまなタイプキャストを取り除くことができると指摘しています。 &quot; new&quot;を使用すると、さらに簡単になります。 Java 5.0で導入された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ループは単なる構文上の砂糖です。カバーの下で、イテレータインスタンスが作成され、コードに従って(修正あり)使用されます。 JITがそれを最適化できると判断できない限り、型キャストも実行されています。
編集:Java 1.5を使用できない場合、これを昔ながらの方法で行うことに固執します。 &quot; processing.org&quot;のような音一緒に行動する必要があります。 Java 1.4.xプラットフォームは本当に時代遅れです。