2010-01-20 25 views
3

如何在Java ME中获得类实例的超类。也就是说,在CLDC 1.1中提供有限功能的Class.getSuperclass()功能?Java ME上的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); 
    } 
} 
+0

是否有所有视图类的通用超?这些方法('createStylerForViewClass'和'getStylerForViewClass')是否属于那个超类?如果是这样,那么为什么需要'clazz'参数? – finnw

+0

是的,他们有一个共同的超类,但你不会实现这些方法。只需使用自己的类调用getStylerForViewClass()以获得最适合他们的样式器。 – PeyloW

回答

1

正如您已经发现的那样,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 

,并添加AC树,并要求其为C超它会给你A,如果你后来添加B它将取代AC超,但是直到错误的样式文件返回了C的某些实例。

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

我没想到一个其他邪恶的黑客,但我真的不能推荐一下:

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

足够好,可以使用。我想我会要求所有的View子类调用'registerClass(MyClass.class)'作为静态初始化器。很难执行,但足够好。你的丑陋的黑客攻击是不可行的,因为'System.err'如果'final'在CLDC,我已经考虑过这个问题,以及:(。 – PeyloW

+0

没有标准的方式来获得在J2ME堆栈跟踪。无论是在运行这个仿真器或使用Symbian手机及其“重定向://”GCF协议。 –

1

你有两个选择:

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

或者,你可以有一个预处理程序在你的代码上运行,并创建一个单独保存的数据结构来保存你的类信息。可能即使是自定义doclet也可以做到这一点。输出可以是描述结构的文本或二进制文件:

ClassA:SuperClass 
ClassB:AnotherSuperClass 
etc. 

通知你可能有问题,通过这种方式混淆。

+0

我个人尝试坚持'instanceof'运营商,并尝试利用有限的一组类。我真的不喜欢使用的预处理器,因为它们可以让你的代码更加晦涩 – Malcolm

+0

我不打算用预处理程序处理的文字。请参阅回复以进行澄清。 –

+0

因为我正在实施框架,所以我无法知道这些超类是什么。我无法控制客户想要使用什么样式的客户端。我只是想创建一个灵活和懒惰的加载方法来为任何给定的类提取正确的样式。 – PeyloW