正如您已经发现的那样,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
并将and添加C
到树中并询问它C
会给你的超类A
,如果你以后添加B
它,它将替换A
为 的超类C
,但直到为某些实例返回错误的样式器C
。
因此,我认为您将必须添加必须首先将祖先类(为其定义了样式器)添加到树中的限制。可能来自覆盖的类的静态初始化程序块createStylerForViewClass
,或视图类本身的静态初始化程序。
我确实想到了另一个邪恶的黑客,但我不能真正推荐它:
- 在
View
构造函数中,创建一个 new Exception
,但不要抛出它。
- 暂时换成
System.err
你自己的作家来写ByteArrayOutputStream
- 调用
printStackTrace()
异常
- 恢复
System.err
到原来的价值
- 从
ByteArrayOutputStream
. 中间类的构造函数的名称将在堆栈跟踪中。现在您可以使用它们查找它们Class.forName()
并将它们添加到树中。