既にお気づきのように、MIDP は、クラスのスーパークラスを取得するためのメソッドも、アプリケーション内のすべてのクラスを列挙するためのメソッドも提供しません。
したがって、できることは、クラス階層を自分で追跡することだけです。
共通のスーパークラスを使用すると、新しいオブジェクトに独自のクラスをスーパークラス コンストラクターのグローバル クラス コレクション (まだ存在しない場合) に追加させることができるため、少し簡単になります。
abstract class View {
protected View() {
classHierarchy.add(this.getClass());
}
}
残念ながら、インスタンスが作成されないため、これは抽象クラスでは機能しません。
クラスの既知のサブセットのスーパークラス/サブクラスの関係を追跡するのは簡単です。例えば:
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
public class ClassHierarchy {
public ClassHierarchy() {
childToParentMap = new Hashtable();
parentToChildMap = new Hashtable();
parentToChildMap.put(Object.class, new Vector());
}
public boolean addClass(Class toAdd) {
if (toAdd.isInterface()) return false;
if (toAdd.equals(Object.class)) return false;
if (childToParentMap.get(toAdd) != null) return false;
addClassBelow(toAdd, Object.class, new Vector());
return true;
}
public Class getParent(Class subclass) {
return (Class) childToParentMap.get(subclass);
}
private void addClassBelow(Class toAdd, Class parent, Vector initialChildren) {
Vector children = (Vector) parentToChildMap.get(parent);
Class reparented;
do {
reparented = null;
for (Enumeration childEnum = children.elements();
childEnum.hasMoreElements();
) {
Class child = (Class) childEnum.nextElement();
if (child.isAssignableFrom(toAdd)) {
addClassBelow(toAdd, child, initialChildren);
return;
} else if (toAdd.isAssignableFrom(child)) {
children.removeElement(child);
initialChildren.addElement(child);
childToParentMap.put(child, toAdd);
// Guard against concurrent modification
reparented = child;
break;
}
}
} while (reparented != null);
children.addElement(toAdd);
childToParentMap.put(toAdd, parent);
parentToChildMap.put(toAdd, initialChildren);
}
private Hashtable childToParentMap;
private Hashtable parentToChildMap;
}
ただし、これにより、後で追加される中間クラスが「見逃される」可能性があります。たとえば、次のクラスがある場合です。
Object >= View >= A >= B >= C
A
とをC
ツリーに追加し、 のスーパークラスを要求C
するA
と、後で追加するとのスーパークラスとしてB
置き換えられますが、 のいくつかのインスタンスに対して間違ったスタイラーが返されるまではそうではありません。A
C
C
したがって、祖先クラス (スタイラーが定義されている) を最初にツリーに追加する必要があるという制限を追加する必要があると思います。おそらく、オーバーライドするクラスの静的初期化子ブロックcreateStylerForViewClass
、またはビュー クラス自体の静的初期化子からです。
私は別の邪悪なハックを考えましたが、あまりお勧めできません:
View
コンストラクターで、新しい を作成しますが、Exception
スローしないでください。
System.err
に書き込む独自のライターと一時的に交換します。ByteArrayOutputStream
printStackTrace()
例外を呼び出す
System.err
元の値に戻す
- からスタック トレースを解析します
ByteArrayOutputStream
。中間クラスのコンストラクターの名前は、スタック トレースに表示されます。これで、 を使用して検索しClass.forName()
、ツリーに追加できます。