Java ME上的Class.getSuperclass()替换?

时间:2010-01-20 15:02:48

标签: java java-me midp cldc

如何在Java ME中获取Class实例的超类。也就是说,使用CLDC 1.1中可用的有限功能伪造Class.getSuperclass()功能?

我想做的是让抽象超类做这样的事情:

public Styler getStylerForViewClass(Class clazz) {
   Styler s = stylers.get(clazz);
   if (s == null) {
     for (Class c = clazz; s == null; c = c.getSuperclass()) {
       if (c == Object.class) {
         throw new IllegalArgumentException("No Styler for " + clazz.getName());
       }
       s = createStylerForViewClass(c);
     }
     stylers.put(clazz, s);
   }
   return s;
}
public Styler createStylerForViewClass(Clazz clazz) {
  if (clazz == View.class) {
    return new DefaultStyler();
  } else {
    return null;
  }
}

子类可以添加如下的特化:

 public Styler createStylerForViewClass(Class clazz) {
   if (clazz == SpecialView.class) {
     return new SpecialStyler();
   } else {
     return super.createSylerForViewClass(clazz);
   }
 }

2 个答案:

答案 0 :(得分:1)

您有两种选择:

如果您知道超类属于有限集,则可以调用instanceof或使用Class.isInstance()方法。

或者,您可以使用预处理器在您的代码上运行,并创建一个单独保存的数据结构,用于保存您的类信息。甚至自定义doclet也可以做到。输出可以是描述结构的文本或二进制文件:

 ClassA:SuperClass
 ClassB:AnotherSuperClass
 etc.

请注意,您可能会以这种方式遇到混淆问题。

答案 1 :(得分:1)

正如您已经发现的那样,MIDP不提供获取类的超类的方法,也不提供枚举应用程序中所有类的方法。

所以你所能做的就是自己跟踪班级层次结构。

拥有一个共同的超类使它稍微容易一些,因为您可以让新对象将自己的类添加到超类构造函数中的全局类集合(如果尚未存在):

abstract class View {
    protected View() {
        classHierarchy.add(this.getClass());
    }
}

但不幸的是,这对抽象类不起作用,因为没有创建任何实例。

跟踪已知类的子类的超类/子类关系很容易。 e.g:

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

并将AC添加到树中,并询问它是C的超类,它会为您提供A,如果您之后添加了B它会将A替换为C的超类,但直到为C的某些实例返回了错误的样式器。

所以我认为你必须添加限制,首先必须将祖先类(为它们定义了样式器)添加到树中。可能来自覆盖createStylerForViewClass的类的静态初始化程序块,或者视图类本身的静态初始化程序。

我确实想到了另一个邪恶的黑客,但我不能真正推荐它:

  • View构造函数中,创建一个新的Exception,但不要抛出它。
  • 暂时将System.err替换为您自己写入ByteArrayOutputStream
  • 的作家
  • 在异常
  • 上调用printStackTrace()
  • System.err恢复为原始值
  • ByteArrayOutputStream解析堆栈跟踪。中间类的构造函数的名称将位于堆栈跟踪中。现在,您可以使用Class.forName()查找它们并将它们添加到树中。